2015-01-14 3 views
0

WPF 앱에서 DirectX로 작업하기 시작했습니다. 내 첫 번째 단계는 간단한 라이브러리를 사용하는 것입니다 : SharpdDX.WPF. 샘플을 기반으로 간단한 선을 그리는 WPF 컨트롤을 구현했습니다. SharpDX.WPF는 D3DImage를 사용하여 WPF에서 이미지를 렌더링합니다. 불행히도 응용 프로그램의 메모리가 항상 증가합니다.SharpDX.WPF 렌더링시 메모리 사용량 증가

클래스 TestControlRenderer : D3D10을 구현했습니다. 그런 재정의 된

_controlInfoConstantBuffer = new ConstantBuffer<ControlParamsShaderData>(Device); 
     Device.VertexShader.SetConstantBuffer(0, _controlInfoConstantBuffer.Buffer); 

애니메이션 리셋 방법을 초기화하기 : 쉐이더에서 사용하는 파라미터와

 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; 

이어서 일정한 완충액 : 정점 셰이더들은 동일한 초기화

 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를 표시하는 것입니다. 컨트롤은 간단하지만 실시간 애니메이션입니다. 그렇게 가능합니까?

+0

않는 당신'폐기()''graphDataVertexBuffer' 수있다? – thumbmunkeys

답변

2

대부분 리소스가 누출됩니다. 그런 다음 어떤이 (적어도 SharpDX 측에) 누출되어 있는지 응용 프로그램 수명의 다양한 지점에서

SharpDX.Diagnostics.ObjectTracker.ReportActiveObjects() 

를 호출 정적 구성 등록

SharpDX.Configuration.EnableObjectTracking = true; 

를 설정하여 볼 수 있습니다. 이러한 개체를 처리하기 위해 코드를 편집 할 수 있습니다. 디버깅 중에 객체 추적 만 활성화하면 성능이 저하됩니다.

SharpDX는 개체가 이미 Diposed (2.4.2 버전 이상)로 실행되지 않았지만 나중에 비활성화 된 경우 COM 개체를 해제하는 데 사용됩니다 (변경 로그 중 하나에서 하나).

또한 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(); 
+0

응답 해 주셔서 감사합니다. 진단 도구는 항상 같은 개체를 보여줍니다. 나는 그것을 제거하거나 생성하지 않기 때문에 객체를 삭제하는 것이 문제가 아니라고 생각합니다. 백 버퍼링 등으로 문제가 될 수 있습니까? 어쩌면 각 프레임이 새로운 작은 텍스처 또는 무언가를 만듭니다. 어떤 방법 으로든 체크인 할 수 있습니까? – Andrzej

+0

Sysinternals Process Explorer를 사용하여 프로세스의 GPU 탭을 확인하십시오. 프로세스 메모리가 증가함에 따라 시간이 지남에 따라 메모리가 증가하면 그래픽 코드와 관련이 있습니다.이러한 메모리 값이 안정적이면 Process Explorer의 .Net 탭을 확인하고 관리되는 개체의 수가 증가하고 있는지 및/또는 15 세대 힙의 크기가 증가했는지 확인하십시오. 그럼 당신의 문제는 비 그래픽 .Net 코드에 있습니다. – NextInLine

관련 문제