3

i have an wpf app and trying to switch from rendering onto winforms control to rendering onto image using d3dimage (cause i want to be able to place some wpf interface on top of rendering image, airspace problem and all that), so i know i need to create directx 9 device and create shared texture, i'm trying to follow other people's examples, but for some reason shared texture creation fails (but not just directx 9 texture, only when i pass handle of directx 11 texture to it's constructor), i tried using both hardware and reference devices for either directx 9 or directx 11, i tried to tweak formats, creation flags, nothing helped, followed all restrictions described here https://learn.microsoft.com/ru-ru/windows/win32/api/d3d11/nf-d3d11-id3d11device-opensharedresource?redirectedfrom=MSDN and still no result, any ideas? xaml:

<Window x:Class="WPFReflectionTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded">
    <Grid>
        <WindowsFormsHost>
            <wf:Control x:Name="WinFormsControl"/>
        </WindowsFormsHost>
    </Grid>
</Window>

cb:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    SharpDX.Direct3D11.Device device = new SharpDX.Direct3D11.Device(DriverType.Hardware, DeviceCreationFlags.None | DeviceCreationFlags.BgraSupport, FeatureLevel.Level_11_0);

    SharpDX.Direct3D11.Texture2D texture = new SharpDX.Direct3D11.Texture2D(device, new Texture2DDescription()
    {
        Width = WinFormsControl.ClientSize.Width,
        Height = WinFormsControl.ClientSize.Height,
        ArraySize = 1,
        BindFlags = BindFlags.RenderTarget,
        Usage = ResourceUsage.Default,
        CpuAccessFlags = CpuAccessFlags.None,
        Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm,
        MipLevels = 1,
        OptionFlags = ResourceOptionFlags.Shared,
        SampleDescription = new SampleDescription(1, 0)
    });

    Direct3DEx d9context = new Direct3DEx();

    DeviceEx d9device = new DeviceEx(d9context,
                                    0,
                                    DeviceType.Hardware,
                                    IntPtr.Zero,
                                    CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve,
                                    new SharpDX.Direct3D9.PresentParameters()
                                    {
                                        Windowed = true,
                                        SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard,
                                        DeviceWindowHandle = WinFormsControl.Handle,
                                        PresentationInterval = PresentInterval.Immediate,
                                    });

    IntPtr renderTextureHandle = texture.QueryInterface<SharpDX.DXGI.Resource>().SharedHandle;
    SharpDX.Direct3D9.Texture d9texture = new SharpDX.Direct3D9.Texture(d9device,
                                                                        texture.Description.Width,
                                                                        texture.Description.Height,
                                                                        1,
                                                                        SharpDX.Direct3D9.Usage.RenderTarget,
                                                                        SharpDX.Direct3D9.Format.A8B8G8R8,
                                                                        Pool.Default,
                                                                        ref renderTextureHandle);
}
2
  • I have windows 10 x64 and nvidia geforce gtx 1060 with the latest drivers installed (in case that matters) Commented Feb 4, 2022 at 5:06
  • forgot to include exception text: "SharpDX.SharpDXException: 'HRESULT: [0x8876086C], Module: [SharpDX.Direct3D9], ApiCode: [D3DERR_INVALIDCALL/InvalidCall], Message: Unknown'" and this one if devices created with debug mode: "System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'" Commented Feb 4, 2022 at 5:59

1 Answer 1

3

Creating DirectX9 3D device as Direct3DEx and DirectX9 device as Device (without Ex) and using hardware device type in both DirectX9 and DirectX11 devices solved the problem, no other combination worked, here is the working code in my case:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    var device = new SharpDX.Direct3D11.Device(DriverType.Hardware, 
        DeviceCreationFlags.Debug | DeviceCreationFlags.BgraSupport, 
        FeatureLevel.Level_11_0);

    var texture = new SharpDX.Direct3D11.Texture2D(device, 
                  new Texture2DDescription()
    {
        Width = WinFormsControl.ClientSize.Width,
        Height = WinFormsControl.ClientSize.Height,
        ArraySize = 1,
        BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
        Usage = ResourceUsage.Default,
        CpuAccessFlags = CpuAccessFlags.None,
        Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
        MipLevels = 1,
        OptionFlags = ResourceOptionFlags.Shared,
        SampleDescription = new SampleDescription(1, 0)
    });
    
    var d9context = new SharpDX.Direct3D9.Direct3DEx();
    
    var d9device = new SharpDX.Direct3D9.Device(d9context, 0, 
                   DeviceType.Hardware, IntPtr.Zero, 
                   CreateFlags.HardwareVertexProcessing, 
                   new SharpDX.Direct3D9.PresentParameters()
    {
        Windowed = true,
        SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard,
        DeviceWindowHandle = WinFormsControl.Handle,
        PresentationInterval = PresentInterval.Default,
    });
    
    var handle = texture.QueryInterface<SharpDX.DXGI.Resource>().SharedHandle;
    var d9texture = new SharpDX.Direct3D9.Texture(d9device, 
                    texture.Description.Width, texture.Description.Height, 1, 
                    SharpDX.Direct3D9.Usage.RenderTarget, 
                    SharpDX.Direct3D9.Format.A8R8G8B8, Pool.Default, 
                    ref handle);
}
Sign up to request clarification or add additional context in comments.

3 Comments

Does your D3D9 texture update correctly after a render cycle? Mine, using the same initialization code as you + using the var surface = d9texture.GetSurfaceLevel(0) to set the backbuffer to the D3DImage only displays the update to the screen after a second or third render.
Oh, If a shared texture is updated on one device ID3D11DeviceContext::Flush must be called on that device., That was it, I just had to call _d3d11Device.ImmediateContext.Flush(); after the render cycle.
Hmm, but that's not it. It started updating the image more frequently, but still most of the time the new rendered content is not being displayed (old frame content still is displayed). PresentInterval.One did not help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.