d2d1debug3.dll!DebugRenderTarget::EndDraw 访问冲突

Posted

技术标签:

【中文标题】d2d1debug3.dll!DebugRenderTarget::EndDraw 访问冲突【英文标题】:d2d1debug3.dll!DebugRenderTarget::EndDraw Access violation 【发布时间】:2016-05-10 01:58:27 【问题描述】:

这个问题类似于:Intermittent Access Violation ID2D1RenderTarget::EndDraw,但我已经完成了该问题中建议的所有内容,但仍然没有接近解决方案。

运行 1D2DRenderTarget::EndDraw 时,我的应用程序(Windows 应用商店应用程序)有时会抛出内存访问冲突异常(并非总是如此,通常是在大量使用几分钟后,并且仅在 Win10 设备中)。根据转储文件,它说:“线程试图读取或写入它没有适当访问权限的虚拟地址。”

变体很少,但在执行 EndDraw 调用时会分解为访问冲突。以下是反汇编和调用堆栈:

d3d10warp.dll!UMDevice::DestroyResource(struct D3D10DDI_HDEVICE,struct D3D10DDI_HRESOURCE)  Unknown
d3d11.dll!NDXGI::CDeviceChild<IDXGIResource1,IDXGISwapChainInternal>::FinalRelease()    Unknown
d3d11.dll!CUseCountedObject<NOutermost::CDeviceChild>::UCDestroy()  Unknown
d3d11.dll!CUseCountedObject<NOutermost::CDeviceChild>::UCReleaseUse()   Unknown
d3d11.dll!NDXGI::CDeviceChild<IDXGISurface,IUnknown>::FinalRelease()    Unknown
d3d11.dll!CUseCountedObject<NOutermost::CDeviceChild>::UCDestroy()  Unknown
d3d11.dll!CDevCtxInterface::CDevCtxInterface<CContext>()    Unknown
d3d11.dll!CContext::TID3D11DeviceContext_SetShaderResources_Amortized<0,4>()    Unknown
d2d1.dll!CD3DDeviceLevel1::ProcessDeferredOperations()  Unknown
d2d1.dll!CHwSurfaceRenderTarget::FlushQueuedOperations()    Unknown
d2d1.dll!CHwSurfaceRenderTarget::EndProcessBatch()  Unknown
d2d1.dll!CHwSurfaceRenderTarget::ProcessBatch() Unknown
d2d1.dll!CBatchSerializer::FlushInternal()  Unknown
d2d1.dll!CBatchSerializer::Flush()  Unknown
d2d1.dll!DrawingContext::FlushBatch()   Unknown
d2d1.dll!DrawingContext::EndDraw()  Unknown
d2d1.dll!D2DDeviceContextBase<ID2D1RenderTarget,ID2D1DeviceContext3,ID2D1DeviceContext3>::EndDraw() Unknown
d2d1debug3.dll!DebugRenderTarget::EndDraw(class DebugLayer &,struct ID2D1RenderTarget *,unsigned __int64 *,unsigned __int64 *)  Unknown
d2d1debug3.dll!DebugRenderTargetGenerated<struct ID2D1BitmapRenderTarget>::EndDraw(unsigned __int64 *,unsigned __int64 *)   Unknown
OZDebugApp_wrt_2013.exe!OZXCanvasD2D::~OZXCanvasD2D() Line 203  C++

反汇编:

679F0EC1  mov         eax,dword ptr [ebx+4]  
679F0EC4  mov         dword ptr [ecx+4],eax  
679F0EC7  jmp         UMDevice::DestroyResource+1CAh (679F0E6Ah)  
679F0EC9  mov         eax,dword ptr [edi+220h]  
679F0ECF  mov         eax,dword ptr [eax+3Ch]  
679F0ED2  test        eax,eax  
679F0ED4  je          UMDevice::DestroyResource+135h (679F0DD5h)  
679F0EDA  cmp         eax,0FFBADBADh  
679F0EDF  je          UMDevice::DestroyResource+135h (679F0DD5h)  
679F0EE5  mov         cl,byte ptr ds:[67B58280h]  
>> 679F0EEB  movzx       eax,byte ptr [eax]  
679F0EEE  add         ecx,eax  
679F0EF0  mov         byte ptr ds:[67B58280h],cl  
679F0EF6  jmp         UMDevice::DestroyResource+135h (679F0DD5h)  
679F0EFB  push        1  

这是另一个变种

msvcrt.dll!__VEC_memcpy()  Unknown
msvcrt.dll!__VEC_memcpy()  Unknown
d2d1.dll!DrawingContext::EndDraw()  Unknown
D2D1Debug3.dll!DebugRenderTarget::EndDraw(class DebugLayer &,struct ID2D1RenderTarget *,unsigned __int64 *,unsigned __int64 *)  Unknown
D2D1Debug3.dll!DebugRenderTargetGenerated<struct ID2D1BitmapRenderTarget>::EndDraw(unsigned __int64 *,unsigned __int64 *)   Unknown
OZDebugApp_wrt_2013.exe!OZXCanvasD2D::~OZXCanvasD2D() Line 203  C++

反汇编:

76C7A3A7  mov         dword ptr [ebp-8],esi  
76C7A3AA  mov         esi,dword ptr [ebp+0Ch]  
76C7A3AD  mov         edi,dword ptr [ebp+8]  
76C7A3B0  mov         ecx,dword ptr [ebp+10h]  
76C7A3B3  shr         ecx,7  
76C7A3B6  jmp         __VEC_memcpy+108h (76C7A3BEh)  
76C7A3B8  lea         ebx,[ebx]  
>> 76C7A3BE  movdqa      xmm0,xmmword ptr [esi]  
76C7A3C2  movdqa      xmm1,xmmword ptr [esi+10h]  
76C7A3C7  movdqa      xmm2,xmmword ptr [esi+20h]  
76C7A3CC  movdqa      xmm3,xmmword ptr [esi+30h]  
76C7A3D1  movdqa      xmmword ptr [edi],xmm0  
76C7A3D5  movdqa      xmmword ptr [edi+10h],xmm1  
76C7A3DA  movdqa      xmmword ptr [edi+20h],xmm2  
76C7A3DF  movdqa      xmmword ptr [edi+30h],xmm3  

我尝试过的事情:

    我检查了多线程。我的应用程序使用一个具有多线程属性的 1D2D 工厂和多个渲染目标,因此默认情况下应该交错绘图。最重要的是,我尝试添加锁,以便每个 BeginDraw、EndDraw、渲染目标创建和 DXGI 相关的东西都处于临界区。 在启用调试层的情况下运行,同时使用 DirectX 控制面板和代码。 生成了故障转储文件,但使用它似乎与仅调试远程计算机完全相同? 实现了一个记录器来为每个渲染目标生成合成/绘图调用和参数。每次运行都会生成大约 40mb 的日志。我检查了崩溃的渲染目标,它们的绘图与早期的一些绘图相同,即)老实说,我看不出绘图级别出了什么问题。

以上方法均无效,非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

原来我没有为 CreateWicBitmapRenderTarget 的一个实例设置临界区。在多线程属性中运行 D2Dfactory 会交错所有 Direct2D 调用,但它不适用于 WIC、DXGI 或其他 D3D 调用。我不得不使用:

Microsoft::WRL::ComPtr<ID2D1Multithread> d2DMultithread;
        d2dFactory.As(&d2DMultithread);
        d2DMultithread->Enter();
        HRESULT targetCreationResult =  d2dFactory->CreateWicBitmapRenderTarget(m_wicBitmap.Get(), &prop, &target);
        d2DMultithread->Leave();

对其他渲染目标创建和 Begin/EndDraw 执行相同操作。通过查看调试中的线程视图,我注意到了上述情况。

【讨论】:

以上是关于d2d1debug3.dll!DebugRenderTarget::EndDraw 访问冲突的主要内容,如果未能解决你的问题,请参考以下文章

在D2D环境下与GDI结合加载位图

5G网络下使用D2D通讯主要应用场景?

Qt5.7 + D2D渲染引擎。 画面闪烁,几乎没图像显示

D2D RPG游戏开发日记--角色/队伍

D3D11:如何将 GDI 文本绘制到 GXDI 表面? (没有 D2D)

ssh连接到centos主机,无法成功连接,报错如下,求大侠赐教!!感谢!!