locked
ISurfaceImageSourceNativeWithD2D ComException E_FAIL in background thread

    Question

  • Hi,

    in my project on C# I use VirtualSurfaceImageSource and ComWrappers to render some data. VSIS is casted to ISurfaceImageSourceNativeWithD2D. ID3D11Device is initialized with D3D11_CREATE_DEVICE_BGRA_SUPPORT and supports multithreding by default. But SISN.beginDraw method cause a ComException with HResult: E_FAIL, if it is called  in background thread. I've try to use this with ID3D11Device (IDXGISurface as output result) and also with ID2D1Device(ID2D1DeviceContext as output result), result was the same.

    It was tested on Win 8.1 and VS2013 pro. Here link on sample Project

    Steps to reproduce:

    1) Open project and launch app

    So, is it possible to make it work from background thread without using C++?




    Wednesday, November 20, 2013 9:51 AM

All replies

  • Hi Mikhail Maksyuta,

    Welcome here!

    I have reproduced your issue and found the reason, please look at the code you written:

     while(true) {
                    if (TaskList.Count != 0)
                    {
                        BackgroundRenderTaskInfo taskInfo = TaskList[0];
                        TaskList.RemoveAt(0);
    
                        ISurfaceImageSourceNativeWithD2D threadsSurface = taskInfo.SurfaceImageSource;
    
                        IDXGISurface surface = null;
                        RECT originalRect = taskInfo.SourceRect;
                        POINT offset = new POINT();
                        Guid guid = new Guid(DirectX.IIDS.IDXGISurface);
                        await uiDispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                        {
                            POINT offset1;
                            threadsSurface.BeginDraw(ref originalRect, ref guid, out surface, out offset1);
    
                            //threadsSurface.BeginDraw(originalRect, out surface, ref offset);
                            offset = offset1;
                        });
    
                        await uiDispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                        {
                            //threadsSurface.SuspendDraw();
                            threadsSurface.EndDraw();
                        });
    
                        Marshal.ReleaseComObject(surface);
                    }
                                }

    When I set a breakpoint, I find it will go into a infinite loop while TaskList.Count==0, and the error is display.

    Just add "else return;" will fix the issue.

    Like this:

    if (TaskList.Count != 0) { BackgroundRenderTaskInfo taskInfo = TaskList[0]; TaskList.RemoveAt(0); ISurfaceImageSourceNativeWithD2D threadsSurface = taskInfo.SurfaceImageSource; IDXGISurface surface = null; RECT originalRect = taskInfo.SourceRect; POINT offset = new POINT(); Guid guid = new Guid(DirectX.IIDS.IDXGISurface); await uiDispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { POINT offset1; threadsSurface.BeginDraw(ref originalRect, ref guid, out surface, out offset1); //threadsSurface.BeginDraw(originalRect, out surface, ref offset); offset = offset1; }); await uiDispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { //threadsSurface.SuspendDraw(); threadsSurface.EndDraw(); }); Marshal.ReleaseComObject(surface); } else return; }

    Hope it is helpful! :)

    Regards!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Thursday, November 21, 2013 7:36 AM
    Moderator

  • When I set a breakpoint, I find it will go into a infinite loop while TaskList.Count==0, and the error is display.

    Just add "else return;" will fix the issue.

    Infinite loop has nothing to do with this issue - it's a simplest sample of background rendering. In case with "else return;" code under condition (TaskList.Count != 0) will never be executed.

    So, here is a problem.

    threadSurface.BeginDraw works fine, if we execute it in UI thread:

     await uiDispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
                            threadsSurface.BeginDraw(ref originalRect, ref guid, out surface, out offset1);
                        });

    But if we execute threadSurface.BeginDraw in background thread, we get ComException with Hresult: E_FAIL

     //await uiDispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
                            threadsSurface.BeginDraw(ref originalRect, ref guid, out surface, out offset1);
    //                    });







    Thursday, November 21, 2013 1:31 PM
  • Hi Mikhail Maksyuta,

    Welcome back!

    Have you tried this sample:

    http://code.msdn.microsoft.com/windowsapps/XAML-SurfaceImageSource-58f7e4d5

    In this sample, casting SurfaceImageSource to ISurfaceImageSourceNativeWithD2D is in this way:

     Microsoft::WRL::ComPtr<ISurfaceImageSourceNative> sisNative;    
        DX::ThrowIfFailed(
            reinterpret_cast<IUnknown*>(this)->QueryInterface(IID_PPV_ARGS(&sisNative))
            );
    
        // Begin drawing - returns a target surface and an offset to use as the top left origin when drawing.
        HRESULT beginDrawHR = sisNative->BeginDraw(updateRectNative, &surface, &offset);

    That's the only thing I have found which is difference from yours.

    Regards!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, November 22, 2013 3:12 AM
    Moderator

  • Have you tried this sample:

    http://code.msdn.microsoft.com/windowsapps/XAML-SurfaceImageSource-58f7e4d5

    In this sample, casting SurfaceImageSource to ISurfaceImageSourceNativeWithD2D is in this way:

    Yes, I have. 

    According to information from MSDN ISurfaceImageSourceNativeWithD2D enables to call methods BeginDraw, SuspendDraw and ResumeDraw in background thread:

    The ISurfaceImageSourceNativeWithD2D interface enables drawing to a SurfaceImageSource or VirtualSurfaceImageSource from one or more background threads, which allows high-performance DirectX rendering off the UI thread. Only call the SetDevice, BeginDraw, and EndDraw methods on ISurfaceImageSourceNativeWithD2D interface, not on the ISurfaceImageSourceNative or IVirtualSurfaceImageSourceNative interfaces. To draw to the surface from a background thread, you must set any DirectX resources, including the Microsoft Direct3D device, Direct3D device context, Direct2D device, and Direct2D device context, to enable multithreading support. You can call the BeginDraw, SuspendDraw, and ResumeDraw methods from any background thread to enable high-performance multithreaded drawing.

    But when method BeginDraw is called from background thread, we get HResult == E_FAIL:

    SurfaceImageSource^ surface = ref new SurfaceImageSource(800, 800);
    IInspectable* sisInspectable = (IInspectable*) reinterpret_cast<IInspectable*>(surface);
    sisInspectable->QueryInterface(__uuidof(ISurfaceImageSourceNativeWithD2D), (void **)&m_sisNative);
    m_sisNative->SetDevice(dxgiDevice.Get());
    POINT offset = { 0, 0 };
    RECT rectangle = { 0, 0, 800, 800 };
    create_task([this, &offset, rectangle]()
    {
    	//do in background thread
    	ComPtr<IDXGISurface> dxgiSurface;
    	GUID guid = __uuidof(IDXGISurface);
    	HRESULT beginDrawHR = m_sisNative->BeginDraw(rectangle, guid, &dxgiSurface, &offset);
    	DX::ThrowIfFailed(beginDrawHR);
    }, task_continuation_context::use_arbitrary()).then([this]()
    {
    	//do in UI thread
    	HRESULT endDrawHR = m_sisNative->EndDraw();
    	DX::ThrowIfFailed(endDrawHR);
    }, task_continuation_context::use_current());


    Here is sample.

    So, how can I use method ISurfaceImageSourceNativeWithD2D.BeginDraw in background thread?

    Friday, November 22, 2013 7:33 AM
  • Hi Mikhail Maksyuta,

    I have reproduced your issue, and I have the same issue which has mentioned here:

    http://answers.flyppdevportal.com/categories/metro/nativecode.aspx?ID=d52b1232-2947-40a5-827e-7826e870a76c

    Please check if your graphics device drivers is the latest.

    Regards!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, November 22, 2013 10:11 AM
    Moderator
  • I have reproduced your issue, and I have the same issue which has mentioned here:

    http://answers.flyppdevportal.com/categories/metro/nativecode.aspx?ID=d52b1232-2947-40a5-827e-7826e870a76c

    Please check if your graphics device drivers is the latest.

    I've already seen issue, you mentioned. Magazine sample works fine with feature level 9_3.

    And issue, you mentioned, is not the same:

    1) I have problem with ISurfaceImageSourceNativeWithD2D in background thread. But in issue, you mentioned, problem was with ISurfaceImageSourceNative in UI thread.

    Graphics device driver is the latest. I've also try to launch my sample on different machines (one with Intel HD graphics 4000, and other with Intel HD graphics 4600).



    Friday, November 22, 2013 11:03 AM
  • Hi Mikhail Maksyuta,

    Welcome here!

    I have tested your sample by clicking right button and left button in turn. The error info:

    page1, page2, page1, error

    page1, page2, page1, page2, error

    page1, page2, page3, page2, error

    page1, page2, page3, page2, page1, error

    I have tried many times, and I am sure that the error is random.

    So I think the error is within the background task. I will report it as bug if it could be passed the confirm. :)

    Thanks for your support on MSDN.

    Regards!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, November 25, 2013 2:17 AM
    Moderator
  • Hello Mikhail,

    Were you ever able to find a solution to this? I am running into the same issue and cannot seem to find a workaround or working example of ISurfaceImageSourceNativeWithD2D.

    Thanks,

    Geoff

    Thursday, May 15, 2014 11:45 PM
  • Hello Mikhail,

    Were you ever able to find a solution to this? I am running into the same issue and cannot seem to find a workaround or working example of ISurfaceImageSourceNativeWithD2D.

    Thanks,

    Geoff

    Hello.

    Unfortunately no. So I gave up on using ISurfaceImageSourceNativeWithD2D and use ISurfaceImageSourceNative instead.


    Friday, June 20, 2014 6:38 AM