频繁更新 Texture2D 会导致进程崩溃 (UpdateSubresource)

Posted

技术标签:

【中文标题】频繁更新 Texture2D 会导致进程崩溃 (UpdateSubresource)【英文标题】:Updating Texture2D frequently causes process to crash (UpdateSubresource) 【发布时间】:2021-12-07 21:53:26 【问题描述】:

我使用 SharpDX 基本上在 directX 进程上渲染浏览器(铬)输出缓冲区。

过程相对简单,我截取 CEF 缓冲区(通过覆盖 OnPaint 方法)并将其写入纹理 2D。

代码比较简单:

纹理创建:

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);
    

这段代码在开始和调整大小时执行。

现在,当 CEF OnDraw 时,我基本上将它们的缓冲区复制到纹理:

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);

那里还有更多代码,但基本上这只是相关的部分。在 OnDraw 频繁发生之前,整个过程都有效。

显然,如果我强制 CEF 频繁绘制,整个主机进程都会死掉。 这发生在UpdateSubresource

所以我的问题是,还有其他更安全的方法吗? (经常更新纹理)

【问题讨论】:

如果它崩溃,这意味着你的代码中存在错误。堆栈跟踪是什么?此外,您可以启用 DirectX 调试层 docs.microsoft.com/en-us/windows/win32/direct3d11/… walbourn.github.io/direct3d-sdk-debug-layer-tricks 如果您滥用 API,它通常会转储有用的信息 @SimonMourier 没有堆栈跟踪,进程就死了。不幸的是,我无法访问 DirectX 层。只要我不尝试在 chrome 层(将调用 OnPaint)上重复执行一些动画,也没有任何迹象表明它存在错误。这使我得出结论,我应该用不同的方法映射内存 您使用 DirectX(甚至通过 SharpDX),因此您可以完全访问 DirectX。至于崩溃,当您使用 Visual Studio 调试您的应用程序并启用所有异常 docs.microsoft.com/en-us/visualstudio/debugger/… 时,您应该会得到一个堆栈跟踪。 @SimonMourier 不幸的是,我有点受限,因为这是在 linux 上测试的(尽管 windows 有同样的问题),我得到的只是这个错误:类型:SEHException SharpDX.Direct3D11,SharpDX.Direct3D11.DeviceContext ::UpdateSubresource 所以问题仍然存在,有没有其他方法可以从内存缓冲区更新纹理?最好是更快、更不容易出错的东西 “错误”不是来自函数本身,也不是你调用它的次数,它来自你的代码。 【参考方案1】:

这个问题的解决方法比较简单,但一开始并不那么明显。

我只是移动了负责更新纹理的代码在渲染循环中,并保持内部缓冲区指针缓存。

【讨论】:

以上是关于频繁更新 Texture2D 会导致进程崩溃 (UpdateSubresource)的主要内容,如果未能解决你的问题,请参考以下文章

也许 QThread 中的 QTLineEdit 范围会导致程序崩溃?

将 HttpClient 设置为太短的超时会导致进程崩溃

windows update更新失败频繁启动是何原因

不频繁的 Handler.post 导致大量丢帧和崩溃

搜狗输入法导致程序崩溃怎么办

绕过 C++ 中的函数以在目标进程中从 ExtTextOut 复制数据字符串时,malloc 会导致崩溃吗?