gpt4 book ai didi

c# - 从 SharpDX 中的数据流读取导致内存泄漏

转载 作者:行者123 更新时间:2023-12-04 00:29:43 26 4
gpt4 key购买 nike

我正在尝试从 SharpDX.DataStream 获取像素。我每秒执行此操作 25 次,这会导致大量内存使用。我想我缺少某种清理工作。

一旦我开始调用 GetColor 方法,内存使用量就开始上升。我尝试过Displosing the class,但没有成功。任何有更多 SharpDX 经验的人都可以指出我所缺少的内容。这很可能是一些简单的事情,比如释放资源,但我陷入了困境。

// Original code by Florian Schnell
// http://www.floschnell.de/computer-science/super-fast-screen-capture-with-windows-8.html

using System;
using System.IO;
using SharpDX;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using Color = System.Drawing.Color;
using Device = SharpDX.Direct3D11.Device;
using MapFlags = SharpDX.DXGI.MapFlags;
using Point = System.Drawing.Point;
using Resource = SharpDX.DXGI.Resource;
using ResultCode = SharpDX.DXGI.ResultCode;

namespace Artemis.Modules.Effects.AmbientLightning
{
internal class ScreenCapture : IDisposable
{
private readonly Device _device;
private readonly Factory1 _factory;
private readonly Texture2D _screenTexture;
private DataStream _dataStream;
private readonly OutputDuplication _duplicatedOutput;
private Resource _screenResource;
private Surface _screenSurface;

public ScreenCapture()
{
// Create device and factory
_device = new Device(DriverType.Hardware);
_factory = new Factory1();

// Creating CPU-accessible texture resource
var texdes = new Texture2DDescription
{
CpuAccessFlags = CpuAccessFlags.Read,
BindFlags = BindFlags.None,
Format = Format.B8G8R8A8_UNorm,
Height = _factory.Adapters1[0].Outputs[0].Description.DesktopBounds.Bottom,
Width = _factory.Adapters1[0].Outputs[0].Description.DesktopBounds.Right,
OptionFlags = ResourceOptionFlags.None,
MipLevels = 1,
ArraySize = 1,
SampleDescription =
{
Count = 1,
Quality = 0
},
Usage = ResourceUsage.Staging
};
_screenTexture = new Texture2D(_device, texdes);

// duplicate output stuff
var output = new Output1(_factory.Adapters1[0].Outputs[0].NativePointer);
_duplicatedOutput = output.DuplicateOutput(_device);
_screenResource = null;
_dataStream = null;
}

public void Dispose()
{
_duplicatedOutput.Dispose();
_screenResource.Dispose();
_dataStream.Dispose();
_factory.Dispose();
}

public DataStream Capture()
{
try
{
OutputDuplicateFrameInformation duplicateFrameInformation;
_duplicatedOutput.AcquireNextFrame(1000, out duplicateFrameInformation, out _screenResource);
}
catch (SharpDXException e)
{
if (e.ResultCode.Code == ResultCode.WaitTimeout.Result.Code ||
e.ResultCode.Code == ResultCode.AccessDenied.Result.Code ||
e.ResultCode.Code == ResultCode.AccessLost.Result.Code)
return null;
throw;
}

// copy resource into memory that can be accessed by the CPU
_device.ImmediateContext.CopyResource(_screenResource.QueryInterface<SharpDX.Direct3D11.Resource>(),
_screenTexture);

// cast from texture to surface, so we can access its bytes
_screenSurface = _screenTexture.QueryInterface<Surface>();

// map the resource to access it
_screenSurface.Map(MapFlags.Read, out _dataStream);

// seek within the stream and read one byte
_dataStream.Position = 4;
_dataStream.ReadByte();

// free resources
_dataStream.Close();
_screenSurface.Unmap();
_screenSurface.Dispose();
_screenResource.Dispose();
_duplicatedOutput.ReleaseFrame();

return _dataStream;
}

/// <summary>
/// Gets a specific pixel out of the data stream.
/// </summary>
/// <param name="surfaceDataStream"></param>
/// <param name="position">Given point on the screen.</param>
/// <returns></returns>
public Color GetColor(DataStream surfaceDataStream, Point position)
{
var data = new byte[4];
surfaceDataStream.Seek(
position.Y*_factory.Adapters1[0].Outputs[0].Description.DesktopBounds.Right*4 + position.X*4,
SeekOrigin.Begin);
surfaceDataStream.Read(data, 0, 4);
return Color.FromArgb(255, data[2], data[1], data[0]);
}
}
}

最佳答案

不确定它是否能解决您的内存问题,但有一些改进:

  • 处置 _screenResource.QueryInterface<SharpDX.Direct3D11.Resource>()
  • 避免通过 DXGI 获取 map _screenSurface = _screenTexture.QueryInterface<Surface>();虽然您可以直接执行此操作 Direct3D11.DeviceContext.Map()
  • 使用 DeviceContext.Map() 的版本返回一个结构体(仅包含非托管内存指针)而不是 DataStream
  • 使用Utilities.Read<ColorBGRA>(intptr)使用正确的字节偏移量来提取数据(请注意 DataStream 还允许直接读取颜色,它不适合与 ReadByte 一起使用)
  • 而不是这个 position.Y*_factory.Adapters1[0].Outputs[0].Description.DesktopBounds.Right*4 + position.X*4 。使用 Map 方法返回的步幅 ( DataBox.RowPitch ) 来偏移到正确的行,而不是纹理的宽度(每行的字节数可以更改,并且可能不会与纹理宽度对齐)

关于c# - 从 SharpDX 中的数据流读取导致内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35990670/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com