0

I am using SharpDX to basically render browser (chromium) output buffer on directX process.

Process is relatively simple, I intercept CEF buffer (by overriding OnPaint method) and write that to a texture2D.

Code is relatively simple:

Texture creation:

public void BuildTextureWrap() {
    var oldTexture = texture;

    texture = new D3D11.Texture2D(DxHandler.Device, new D3D11.Texture2DDescription() {
        Width = overlay.Size.Width,
        Height = overlay.Size.Height,
        MipLevels = 1,
        ArraySize = 1,
        Format = DXGI.Format.B8G8R8A8_UNorm,
        SampleDescription = new DXGI.SampleDescription(1, 0),
        Usage = D3D11.ResourceUsage.Default,
        BindFlags = D3D11.BindFlags.ShaderResource,
        CpuAccessFlags = D3D11.CpuAccessFlags.None,
        OptionFlags = D3D11.ResourceOptionFlags.None,
    });

    var view = new D3D11.ShaderResourceView(
        DxHandler.Device,
        texture,
        new D3D11.ShaderResourceViewDescription {
            Format = texture.Description.Format,
            Dimension = D3D.ShaderResourceViewDimension.Texture2D,
            Texture2D = { MipLevels = texture.Description.MipLevels },
        }
    );

    textureWrap = new D3DTextureWrap(view, texture.Description.Width, texture.Description.Height);

    if (oldTexture != null) {
        obsoleteTextures.Add(oldTexture);
    }
}

That piece of code is executed at start and when resize is happening.

Now when CEF OnDraw I basically copy their buffer to texture:

var destinationRegion = new D3D11.ResourceRegion {
    Top = Math.Min(r.dirtyRect.y, texDesc.Height),
    Bottom = Math.Min(r.dirtyRect.y + r.dirtyRect.height, texDesc.Height),
    Left = Math.Min(r.dirtyRect.x, texDesc.Width),
    Right = Math.Min(r.dirtyRect.x + r.dirtyRect.width, texDesc.Width),
    Front = 0,
    Back = 1,
};

// Draw to the target
var context = targetTexture.Device.ImmediateContext;
context.UpdateSubresource(targetTexture, 0, destinationRegion, sourceRegionPtr, rowPitch, depthPitch);

There are some more code out there but basically this is only relevant piece. Whole thing works until OnDraw happens frequently.

Apparently if I force CEF to Paint frequently, whole host process dies. This is happening at UpdateSubresource.

So my question is, is there another, safer way to do this? (Update texture frequently)

Kaminari
  • 1,387
  • 3
  • 17
  • 32
  • If it crashes, it means there's a bug in your code. What's the stack trace? Also, you can enable the DirectX debug layer https://learn.microsoft.com/en-us/windows/win32/direct3d11/using-the-debug-layer-to-test-apps https://walbourn.github.io/direct3d-sdk-debug-layer-tricks/ it usually dumps useful information if you misuse the API – Simon Mourier Oct 21 '21 at 06:56
  • @SimonMourier There is no stack trace, process just dies. Unfortunately I do not have access to DirectX layer. Also there is nothing that would indicate a bug as it works for as long as i don't try to perform some animations on chrome layer (which would call OnPaint) repeatedly. That leads me to conclusion that i should map memory with different method – Kaminari Oct 21 '21 at 07:29
  • You use DirectX (even through SharpDX), so you have full access to DirectX. As for the crash, when you debug your app using Visual Studio with all exceptions enabled https://learn.microsoft.com/en-us/visualstudio/debugger/managing-exceptions-with-the-debugger, you should get a stack trace. – Simon Mourier Oct 21 '21 at 07:33
  • @SimonMourier Unfortunately I am a bit limited as this is being tested on linux (although windows has same issue), All i get is this error: Type: SEHException SharpDX.Direct3D11, SharpDX.Direct3D11.DeviceContext::UpdateSubresource So the question remains, is there any other way to update texture from memorybuffer? Preferably something faster and less error prone – Kaminari Oct 21 '21 at 07:59
  • The "error" doesn't come from the function itself or the number of times you call it, it comes from your code. – Simon Mourier Oct 21 '21 at 08:07
  • @SimonMourier Even if you say this, there surely has to be some way to check this, or a hint where to look. Source pointer is being allocated once. It has constant size = W * H * 4 and when cef does the OnPaint i simply copy entire buffer from there. – Kaminari Oct 21 '21 at 08:09

1 Answers1

2

Solution to this problem was relatively simple yet not so obvious at the beginning.

I simply moved the code responsible for updating texture inside render loop and just keep internal buffer pointer cached.

Kaminari
  • 1,387
  • 3
  • 17
  • 32