SharpDX.WPF 渲染期间增加内存使用
SharpDX.WPF Increasing memory usage during rendering
我已经开始在 WPF 应用程序中使用 DirectX。我的第一步是使用简单的库:
SharpdDX.WPF。基于示例,我实现了 WPF 控件绘制简单的线条。 SharpDX.WPF 使用 D3DImage 在 WPF 中渲染图像。
不幸的是,应用程序的内存一直在增加。
我实现了 class TestControlRenderer:D3D10。
顶点着色器初始化如下:
var sizeInBytes = dataLength * sizeof(int) * 3;
var bufferDescription = new BufferDescription(
sizeInBytes,
ResourceUsage.Dynamic,
BindFlags.VertexBuffer,
CpuAccessFlags.Write,
ResourceOptionFlags.None);
using (var stream = new DataStream(sizeInBytes, true, true))
{
stream.Position = 0;
_graphDataVertexBuffer = new SharpDX.Direct3D10.Buffer(Device, stream, bufferDescription);
}
Device.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(_graphDataVertexBuffer, sizeof(int) * 3, 0));
Device.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineStrip;
然后使用着色器中使用的参数常量缓冲区:
_controlInfoConstantBuffer = new ConstantBuffer<ControlParamsShaderData>(Device);
Device.VertexShader.SetConstantBuffer(0, _controlInfoConstantBuffer.Buffer);
要初始化动画重置方法是这样重写的:
base.Reset(args);
if (args.RenderSize.Width == 0) return;
_drawArgs = args;
InitVertexBuffer(dataLength);
_controlInfoConstantBuffer.Value = new ControlParamsShaderData
{
SamplesInControl = dataLength,
MinSignalDataY = -1500,
MaxSignalDataY = 1500
};
Device.VertexShader.SetConstantBuffer(0, _controlInfoConstantBuffer.Buffer);
最后一步是RenderScene方法:
public override void RenderScene(DrawEventArgs args)
{
if (args.RenderSize.Width == 0) return;
Device.ClearRenderTargetView(RenderTargetView, Color.Transparent);
using (var stream = _graphDataVertexBuffer.Map(MapMode.WriteDiscard, SharpDX.Direct3D10.MapFlags.None))
{
for (int i = 0; i < Data.Length; i++)
{
stream.Write(new Vector3(i, Data[i], 0));
}
}
_graphDataVertexBuffer.Unmap();
Device.Draw(Data.Length, 0);
}
渲染由 DispatcherTimer 控制,其中 OnTickMethod 使用点坐标更新数组,然后调用 Render() 方法。
我的问题很简单,是内存泄漏还是在每次渲染迭代时产生的东西?
我不更改后备缓冲区或创建其他对象。只改变数据数组,将其更新到 GPU 和着色器处理它以显示。
我的情况是在一个屏幕上显示大约 30 个 wpf 控件宽度的 DirectX。控件带有简单但实时的动画。这样可以吗?
您很可能正在泄漏资源。您可以通过设置静态配置 属性
来查看
SharpDX.Configuration.EnableObjectTracking = true;
然后调用
SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects()
在您的应用程序生命周期的不同时间点查看是否有任何泄漏(至少在 SharpDX 方面)。您可以编辑代码以确保处置这些对象。仅在调试时启用对象跟踪 - 这会影响性能。
SharpDX 曾经在终结器 运行 对象尚未被处置时释放 COM 对象(至少在版本 2.4.2 中如此),但后来禁用了它(他们在其中一个详细说明了原因变更日志,我忘了是哪一个)。
此外,DirectX requires that you release objects in the reverse order they were created - 这会造成难以调试的内存泄漏。所以当你的代码是
var device = new Devie(...);
var effect = new Effec(Device, byteCode);
technique = effect.GetTechniqueByName(techniqueName);
inputLayout = new InputLayout(Device, _technique.GetPassByIndex(0).Description.Signature, ...);
那么你的处置代码必须是
_inputLayout.Dispose();
_technique.Dispose();
_effect.Dispose();
_device.Dispose();
我已经开始在 WPF 应用程序中使用 DirectX。我的第一步是使用简单的库: SharpdDX.WPF。基于示例,我实现了 WPF 控件绘制简单的线条。 SharpDX.WPF 使用 D3DImage 在 WPF 中渲染图像。 不幸的是,应用程序的内存一直在增加。
我实现了 class TestControlRenderer:D3D10。 顶点着色器初始化如下:
var sizeInBytes = dataLength * sizeof(int) * 3;
var bufferDescription = new BufferDescription(
sizeInBytes,
ResourceUsage.Dynamic,
BindFlags.VertexBuffer,
CpuAccessFlags.Write,
ResourceOptionFlags.None);
using (var stream = new DataStream(sizeInBytes, true, true))
{
stream.Position = 0;
_graphDataVertexBuffer = new SharpDX.Direct3D10.Buffer(Device, stream, bufferDescription);
}
Device.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(_graphDataVertexBuffer, sizeof(int) * 3, 0));
Device.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineStrip;
然后使用着色器中使用的参数常量缓冲区:
_controlInfoConstantBuffer = new ConstantBuffer<ControlParamsShaderData>(Device);
Device.VertexShader.SetConstantBuffer(0, _controlInfoConstantBuffer.Buffer);
要初始化动画重置方法是这样重写的:
base.Reset(args);
if (args.RenderSize.Width == 0) return;
_drawArgs = args;
InitVertexBuffer(dataLength);
_controlInfoConstantBuffer.Value = new ControlParamsShaderData
{
SamplesInControl = dataLength,
MinSignalDataY = -1500,
MaxSignalDataY = 1500
};
Device.VertexShader.SetConstantBuffer(0, _controlInfoConstantBuffer.Buffer);
最后一步是RenderScene方法:
public override void RenderScene(DrawEventArgs args)
{
if (args.RenderSize.Width == 0) return;
Device.ClearRenderTargetView(RenderTargetView, Color.Transparent);
using (var stream = _graphDataVertexBuffer.Map(MapMode.WriteDiscard, SharpDX.Direct3D10.MapFlags.None))
{
for (int i = 0; i < Data.Length; i++)
{
stream.Write(new Vector3(i, Data[i], 0));
}
}
_graphDataVertexBuffer.Unmap();
Device.Draw(Data.Length, 0);
}
渲染由 DispatcherTimer 控制,其中 OnTickMethod 使用点坐标更新数组,然后调用 Render() 方法。
我的问题很简单,是内存泄漏还是在每次渲染迭代时产生的东西? 我不更改后备缓冲区或创建其他对象。只改变数据数组,将其更新到 GPU 和着色器处理它以显示。 我的情况是在一个屏幕上显示大约 30 个 wpf 控件宽度的 DirectX。控件带有简单但实时的动画。这样可以吗?
您很可能正在泄漏资源。您可以通过设置静态配置 属性
来查看SharpDX.Configuration.EnableObjectTracking = true;
然后调用
SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects()
在您的应用程序生命周期的不同时间点查看是否有任何泄漏(至少在 SharpDX 方面)。您可以编辑代码以确保处置这些对象。仅在调试时启用对象跟踪 - 这会影响性能。
SharpDX 曾经在终结器 运行 对象尚未被处置时释放 COM 对象(至少在版本 2.4.2 中如此),但后来禁用了它(他们在其中一个详细说明了原因变更日志,我忘了是哪一个)。
此外,DirectX requires that you release objects in the reverse order they were created - 这会造成难以调试的内存泄漏。所以当你的代码是
var device = new Devie(...);
var effect = new Effec(Device, byteCode);
technique = effect.GetTechniqueByName(techniqueName);
inputLayout = new InputLayout(Device, _technique.GetPassByIndex(0).Description.Signature, ...);
那么你的处置代码必须是
_inputLayout.Dispose();
_technique.Dispose();
_effect.Dispose();
_device.Dispose();