2015-01-12 17 views
5

Ho un progetto SharpDX che è molto vicino al completamento. Usa un Kinect per l'interazione. Per questo motivo il mio progetto utilizza WPF sia per la regione Kinect che per l'oggetto KinectUserViewer. SharpDX ha funzionato benissimo finora per tutto, tuttavia, quando arriva a una certa parte del programma che utilizza direct3D pesantemente, inizia a lampeggiare. Questo è apparentemente collegato al fatto che D3Dimage (utilizzato da SharpDXElement in MainWindow.xaml) può essere "fondamentalmente rotto e inadatto per un rendering D3D efficiente in WPF" [1]. C'è un modo per mantenere i miei elementi WPF e non avere sfarfallio con direct3D?Hai bisogno di SharpDXElement alternativo. Soluzione alternativa per sharpDX WPF sfarfallio

+0

ti invitiamo a mostrare un po 'di codice correlato? Sarebbe di grande aiuto vedere dove sei quando rispondi a una domanda come questa. – rfornal

+0

Ha oltre 15000 righe di codice. È difficile trovare il codice pertinente. Usa la classe toolkit.game per il ciclo draw e update. Io uso principalmente spritebatch ma alcune parti usano sia xna che direct3D, inclusa la parte in questione. C'è una parte in particolare che pensi potrebbe aiutare? – Asor

+0

Dire, ho dato un'occhiata al tuo link e quando ho guardato il contesto della tua citazione, hanno anche menzionato una soluzione limitata usando un Windows Form. Se ho capito la soluzione alternativa, che essenzialmente ospitare un Windows Form nell'area di sostituzione D3DImage - e penso * solo * quell'area non sarebbe in grado di utilizzare gli elementi XAML. questo funzionerebbe per te? O mi sto perdendo qualcosa sulla natura della soluzione? –

risposta

5

Probabilità di sfarfallio indica che la GPU non ha terminato di eseguire il rendering del frame prima che D3DImage tenti di copiarlo sul suo buffer anteriore. Questo può facilmente accadere in WPF perché WPF non usa il meccanismo standard di presentazione a una catena di scambio per il rendering di un frame. Invece, la maggior parte del codice utilizza qualcosa di simile al seguente:

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

Questo è almeno il modello seguito da SharpDXElement.InvalidateRender - non vedo l'Device.Flush() in quel file, ma ho il sospetto che è nel codice chiamante.

Il problema è che Device.Flush() non è sincrono. Funziona bene per carichi leggeri di GPU - la GPU finisce prima che il codice di blocco/sblocco sia finito - ma per carichi più pesanti spesso non ha terminato il rendering, risultando in una cornice vuota almeno per alcuni fotogrammi. Questo appare come sfarfallio.

La cosa bella dell'open source è che è possibile modificare il codice. Per verificare questo problema e fornire una soluzione facile (se hacker), provare a dare la GPU un po 'più di tempo:

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

Se che riduce o elimina la vostra luce intermittente, questo è il vostro problema. Una soluzione più approfondita, almeno per Direct3D 10 o 11, è a use query events as described in this question.

Il problema con l'utilizzo di Windows Form è che si finisce con problemi di spazio aereo WPF (la mancanza di capacità per gli elementi WPF di disegnare sopra la finestra secondaria). Airspace issues can be fixed, ma il lavoro è un po 'più complesso rispetto alla modifica di SharpDXElement.

1

Ho avuto lo stesso problema, DeviceCreationFlags.SingleThreaded mi ha aiutato.

2

Il problema non è il meccanismo di blocco. Normalmente si usa Present per disegnare per presentare l'immagine. Present attenderà fino a quando tutto il disegno è pronto. Con D3DImage non si utilizza il metodo Present(). Invece di Presentare, blocchi, aggiungi un DirtyRect e sblocca lo D3DImage.

Il rendering viene eseguito in modo asincrono, pertanto quando si sblocca, le azioni di disegno potrebbero non essere pronte. Questo sta causando l'effetto di sfarfallio. A volte vedi oggetti disegnati a metà. Una soluzione scadente (ho provato con) sta aggiungendo un piccolo ritardo prima dello sblocco. Ha aiutato un po ', ma non è stata una soluzione chiara. È stato terribile!

Soluzione:

ho continuato con qualcos'altro; Mi stavo sviluppando con MSAA (antialiasing) e il primo problema che ho affrontato è stato; MSAA non può essere fatto sulla texture condivisa dx11/dx9, quindi ho deciso di eseguire il rendering su una nuova trama (dx11) e creare una copia sulla texture condivisa dx9. Ho sbattuto la testa sul tavolo, perché ora era anti-aliased e senza sfarfallio !!

Sembra che l'azione di copia thr attende fino a quando tutto il disegno è pronto (ovviamente) ora aiuta a completare il disegno.

Quindi, la creazione di una copia di riserva della struttura:

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

(_dx11BackpageTexture è la trama condivisa e _dx11RenderTexture è il DX11 tessitura MSAA) attenderà fino a quando il rendering è pronto e creerà una copia.

Questo è come mi sono liberato del tremolio ....

+0

BRILLANTE. Andando a provare questo. Sono stati afflitti da sfarfallio DX11/DX9 per anni e ho provato così tanti diversi hack/soluzioni alternative ... –