2015-01-12 7 views
5

SharpDX 프로젝트가 거의 완료되었습니다. 상호 작용을 위해 Kinect를 사용합니다. 이 때문에 내 프로젝트는 Kinect 영역과 KinectUserViewer 객체 모두에 대해 WPF를 사용합니다. SharpDX는 지금까지 모든 작업에 효과적 이었지만, direct3D를 많이 사용하는 프로그램의 특정 부분에 도달하면 깜박이기 시작합니다. 이는 D3Dimage (MainWindow.xaml의 SharpDXElement에서 사용)가 WPF의 효율적인 D3D 렌더링에 "근본적으로 손상되어 부적합"할 수 있다는 사실에 분명히 연결되어 있습니다. [1]. 내 WPF 요소를 유지하고 direct3D로 깜박 거리지 않는 방법이 있습니까?SharpDXElement 대안이 필요합니다. sharpDX WPF 깜박임 해결 방법

+0

당신은 몇 가지 관련 코드를 보여 주시겠습니까? 이런 질문에 답을 할 때 당신이 어디에 있는지 엄청나게 알 수 있습니다. – rfornal

+0

그것은 15000 라인이 넘습니다. 관련 코드를 찾기가 어렵습니다. 그리기 및 업데이트 루프에 toolkit.game 클래스를 사용합니다. 주로 spritebatch를 사용하지만 일부는 문제의 파트를 포함하여 xna와 direct3D를 사용합니다. 특히 도움이 될만한 부분이 있습니까? – Asor

+0

말하자면, 귀하의 링크를 살펴 보았습니다. 귀하의 견적 문맥을 살펴 보았을 때 Windows Form을 사용하는 제한된 해결 방법에 대해서도 언급했습니다. 이 해결 방법을 이해하면 D3DImage 대체 영역에 Windows Form이 기본적으로 포함됩니다.이 영역 만 XAML 요소를 사용할 수 없다고 생각합니다. 그게 너에게 도움이 되겠니? 아니면 해결 방법의 특성에 대해 뭔가 빠졌습니까? –

답변

5

깜박임은 D3DImage가 프레임을 프런트 버퍼에 복사하려고하기 전에 GPU가 프레임 렌더링을 완료하지 않았 음을 나타냅니다. WPF는 프레임을 렌더링하기 위해 스왑 체인에 제공하는 표준 메커니즘을 사용하지 않기 때문에 WPF에서 쉽게 발생할 수 있습니다. - 내가 그 파일의 Device.Flush() 표시되지 않습니다하지만 난 그것을 호출 코드에 의심 SharpDXElement.InvalidateRender 다음에 적어도 패턴의

// rendering code 
Device.Flush(); // or equivalent, depending on Direct3D version used 
D3DImage.Lock(); 
D3DImage.AddDirtyRect(...); 
D3DImage.Unlock(); 

대신, 대부분의 코드는 다음과 같은 것을 사용합니다.

Device.Flush()은 (는) 동기가 아닙니다. 가벼운 GPU로드 (GPU가 잠금/잠금 해제 코드가 끝나기 전에 완료됩니다.)가 좋지만 무거운로드의 경우 렌더링이 완료되지 않아서 종종 일부 프레임의 경우 빈 프레임이됩니다. 이것은 깜박임으로 나타납니다.

오픈 소스에 대한 좋은 점은 코드를 수정할 수 있다는 것입니다. 이 문제를 확인하고 쉽게 (있는 경우 hackish) 솔루션을 제공하기 위해, GPU 조금 더 많은 시간을 제공하려고 :

D3DImage.Lock(); 
Thread.Sleep(2); // 2ms 
D3DImage.AddDirtyRect(...); 
D3DImage.Unlock(); 

을 그 감소 또는 깜박임을 제거하면이 문제입니다. 적어도 Direct3D 10 또는 11의 경우보다 철저한 솔루션은 use query events as described in this question입니다.

Windows Forms 사용시 문제는 WPF 영역 문제 (하위 창 위에 WPF 항목을 그리는 기능이 없음)로 끝나는 것입니다. Airspace issues can be fixed이지만 SharpDXElement를 편집하는 것보다 훨씬 복잡한 작업입니다.

1

나는 똑같은 문제가있어서 DeviceCreationFlags.SingleThreaded 나를 도왔다.

2

문제는 잠금 메커니즘이 아닙니다. 일반적으로 Present을 사용하여 이미지를 그립니다. Present은 모든 도면이 준비 될 때까지 대기합니다. D3DImage에서는 Present() 메서드를 사용하지 않습니다. 프리젠 테이션하는 대신 DirtyRect를 잠그고 D3DImage의 잠금을 해제합니다.

렌더링이 asynchrone으로 끝나면 잠금 해제 할 때 그리기 작업이 준비되지 않았을 수 있습니다. 이로 인해 플리커 효과가 발생합니다. 때로는 항목 절반이 그려집니다. 가난한 솔루션 (테스트 해본 결과)은 잠금 해제하기 전에 작은 지연을 추가하고 있습니다. 그것은 조금 도움이되었지만 그것은 깔끔한 해결책이 아니 었습니다. 그것은 끔찍했다!

솔루션 : 뭔가 다른 계속

; 나는 MSAA (안티 앨리어싱)으로 expirimenting하고 내가 직면 한 첫 번째 문제는; MSAA는 dx11/dx9 공유 텍스처에서 수행 할 수 없기 때문에 새 텍스처 (dx11)으로 렌더링하고 dx9 공유 텍스처에 대한 복사본을 만듭니다. 나는 이제 앤티 앨리어스 (anti-aliased)와 플릭 킹 (flicking)이 없기 때문에 테이블 위에서 머리를 때렸다.

복사 작업이 모든 도면이 준비 될 때까지 기다리는 것처럼 보입니다 (당연히) 이제 도면을 완성하는 데 도움이됩니다.

그래서, 텍스처의 사본 작성 :

DXDevice11.Device.ImmediateContext.ResolveSubresource(
    _dx11RenderTexture, 0, _dx11BackpageTexture, 0, ColorFormat); 

(_dx11BackpageTexture하면 공유 질감과 _dx11RenderTexture는 MSAA의 DX11 텍스처입니다) 렌더링이 준비하고 복사본을 생성 할 때까지이 대기합니다.

이 내가 깜박 거림을 없애있어 어떻게 ....

+0

BRILLIANT. 이것을 시도해보십시오. 수년간 DX11/DX9의 깜박임에 시달리고 많은 해킹/해결 방법을 시도했습니다 ... –