更新 Texture2D 经常导致进程崩溃(UpdateSubresource)
Updating Texture2D frequently causes process to crash (UpdateSubresource)
我主要使用 SharpDX 在 directX 进程上渲染浏览器 (chromium) 输出缓冲区。
过程比较简单,我拦截CEF缓冲区(通过覆盖OnPaint方法)并将其写入texture2D。
代码比较简单:
纹理创建:
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
。
所以我的问题是,还有其他更安全的方法吗? (经常更新贴图)
这个问题的解决方案比较简单,但一开始并不那么明显。
我只是将负责更新纹理的代码 移到渲染循环 中,并只保留缓存的内部缓冲区指针。
我主要使用 SharpDX 在 directX 进程上渲染浏览器 (chromium) 输出缓冲区。
过程比较简单,我拦截CEF缓冲区(通过覆盖OnPaint方法)并将其写入texture2D。
代码比较简单:
纹理创建:
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
。
所以我的问题是,还有其他更安全的方法吗? (经常更新贴图)
这个问题的解决方案比较简单,但一开始并不那么明显。
我只是将负责更新纹理的代码 移到渲染循环 中,并只保留缓存的内部缓冲区指针。