Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym temacie opisano dodano obsługę trybu przerzucania w systemie Windows 7 i skojarzonych z nim obecnych statystyk w programie Direct3D 9Ex i Programie Desktop Window Manager. Aplikacje docelowe obejmują aplikacje do prezentacji wideo lub klatek na podstawie klatek. Aplikacje korzystające z trybu przerzucania bezpośredniego 3D 9Ex obecnie zmniejszają obciążenie zasobów systemowych po włączeniu usługi DWM. Prezentowanie ulepszeń statystyk związanych z prezentem trybu przerzucania umożliwia aplikacjom Direct3D 9Ex lepszą kontrolę nad szybkością prezentacji dzięki udostępnianiu informacji zwrotnych i mechanizmów poprawek w czasie rzeczywistym. Dostępne są szczegółowe wyjaśnienia i wskaźniki do przykładowych zasobów.
Ten temat zawiera następujące sekcje.
- Ulepszone informacje o programie Direct3D 9Ex dla systemu Windows 7
- prezentacji trybu przerzucania direct3D 9EX
-
model programowania i interfejsy API
- Jak wyrazić zgodę na modelu przerzucania modelu Direct3D 9Ex
- wskazówki dotyczące projektowania dla aplikacji direct3D 9Ex Flip Model
- synchronizacja ramek aplikacji Direct3D 9Ex Flip Model
- synchronizacja ramek dla aplikacji okiennych, gdy usługa DWM jest wyłączona
- Walk-Through modelu przerzucania w trybie Direct3D 9D i prezentowania statystyk
- wnioski dotyczące ulepszeń funkcji Direct3D 9Ex
- wywołanie do akcji
- Tematy pokrewne
Co ulepszono w przypadku funkcji Direct3D 9Ex dla systemu Windows 7
Prezentacja w trybie przerzucania direct3D 9Ex to ulepszony tryb prezentowania obrazów w trybie Direct3D 9Ex, który efektywnie przekazuje renderowane obrazy do programu Windows 7 Desktop Window Manager (DWM) na potrzeby kompozycji. Począwszy od systemu Windows Vista, DWM komponuje cały pulpit. Gdy usługa DWM jest włączona, aplikacje trybu okiennego prezentują swoją zawartość na pulpicie przy użyciu metody o nazwie Blt Mode Present to DWM (lub Blt Model). Dzięki modelowi Blt DWM utrzymuje kopię powierzchni renderowanej w trybie Direct3D 9Ex dla kompozycji pulpitu. Gdy aplikacja zostanie zaktualizowana, nowa zawartość zostanie skopiowana na powierzchnię DWM za pomocą pliku blt. W przypadku aplikacji zawierających zawartość Direct3D i GDI dane GDI są również kopiowane na powierzchnię DWM.
Dostępna w systemie Windows 7, tryb przerzucania do DWM (lub Flip Model) to nowa metoda prezentacji, która zasadniczo umożliwia przekazywanie dojścia powierzchni aplikacji między aplikacjami trybu okiennego i DWM. Oprócz zapisywania zasobów funkcja Flip Model obsługuje ulepszone obecne statystyki.
Obecne statystyki to informacje o chronometrażu, których aplikacje mogą używać do synchronizowania strumieni wideo i audio oraz odzyskiwania po błędach odtwarzania wideo. Informacje o chronometrażu klatek w obecnych statystykach umożliwiają aplikacjom dostosowanie częstotliwości prezentacji ramek wideo w celu zapewnienia bezproblemowej prezentacji. W systemie Windows Vista, gdzie DWM utrzymuje odpowiednią kopię powierzchni ramki dla kompozycji pulpitu, aplikacje mogą używać obecnych statystyk dostarczonych przez DWM. Ta metoda uzyskiwania obecnych statystyk będzie nadal dostępna w systemie Windows 7 dla istniejących aplikacji.
W systemie Windows 7 aplikacje oparte na modelu Direct3D 9Ex, które przyjmują model Flip Model, powinny używać interfejsów API D3D9Ex w celu uzyskania obecnych statystyk. Gdy funkcja DWM jest włączona, tryb okienny i tryb wyłączności trybu pełnoekranowego Direct3D 9Ex mogą oczekiwać tych samych obecnych informacji statystycznych podczas korzystania z modelu przerzucania. Funkcja Direct3D 9Ex Flip Model przedstawia statystyki umożliwiające aplikacjom wykonywanie zapytań dotyczących obecnych statystyk w czasie rzeczywistym, a nie po wyświetlaniu ramki na ekranie; te same obecne informacje statystyczne są dostępne dla aplikacji z włączonym trybem okien Flip-Model jako aplikacje pełnoekranowe; Dodatkowa flaga w interfejsach API D3D9Ex umożliwia aplikacjom Flip Model efektywne odrzucanie późnych ramek w czasie prezentacji.
Model przerzucania bezpośredniego 3D 9D powinien być używany przez nowe aplikacje do prezentacji wideo lub klatek na podstawie klatek, które są przeznaczone dla systemu Windows 7. Ze względu na synchronizację między dwM i środowiskiem uruchomieniowym Direct3D 9Ex aplikacje korzystające z modelu przerzucania powinny określać między 2 do 4 backbuffers, aby zapewnić płynną prezentację. Te aplikacje korzystające z obecnych informacji statystycznych będą korzystać z ulepszeń statystyk z włączoną obsługą przerzucania modelu.
Prezentacja trybu przerzucania Direct3D 9EX
Ulepszenia wydajności trybu przerzucania direct3D 9Ex są znaczące w systemie, gdy usługa DWM jest włączona i gdy aplikacja jest w trybie okna, a nie w trybie wyłączności pełnoekranowym. W poniższej tabeli i ilustracji przedstawiono uproszczone porównanie użycia przepustowości pamięci i odczytów i zapisów aplikacji okiennych, które wybierają opcję Przerzucanie modelu w porównaniu z domyślnym użyciem modelu Blt.
| Tryb Blt obecny w usłudze DWM | Tryb przerzucania D3D9Ex obecny w usłudze DWM |
|---|---|
| 1. Aplikacja aktualizuje ramkę (zapis) |
1. Aplikacja aktualizuje ramkę (zapis) |
| 2. Środowisko uruchomieniowe Direct3D kopiuje zawartość powierzchni do powierzchni przekierowania DWM (odczyt, zapis) |
2. Środowisko uruchomieniowe Direct3D przekazuje powierzchnię aplikacji do usługi DWM |
| 3. Po zakończeniu kopiowania udostępnionej powierzchni dwM renderuje powierzchnię aplikacji na ekranie (odczyt, zapis) |
3. Usługa DWM renderuje powierzchnię aplikacji na ekranie (odczyt, zapis) |
Tryb przerzucania obecny zmniejsza użycie pamięci systemowej przez zmniejszenie liczby odczytów i zapisów przez środowisko uruchomieniowe Direct3D dla kompozycji ramek okiennych przez DWM. Zmniejsza to zużycie energii przez system i ogólne użycie pamięci.
Aplikacje mogą korzystać z trybu direct3D 9Ex Flip Mode prezentować ulepszenia statystyk, gdy usługa DWM jest włączona, niezależnie od tego, czy aplikacja jest w trybie okiennym, czy w trybie wyłączności pełnoekranowym.
Model programowania i interfejsy API
Nowe aplikacje wideo lub oceny szybkości klatek, które korzystają z interfejsów API Direct3D 9Ex w systemie Windows 7, mogą korzystać z pamięci i oszczędności energii oraz ulepszonej prezentacji oferowanej przez tryb przerzucania obecny podczas uruchamiania w systemie Windows 7. (W przypadku uruchamiania w poprzednich wersjach systemu Windows środowisko uruchomieniowe Direct3D domyślnie wykonuje aplikację w trybie Blt Mode Present).
Funkcja Flip Mode Present wiąże się z tym, że aplikacja może korzystać z obecnych w czasie rzeczywistym mechanizmów sprzężenia zwrotnego i korekty, gdy usługa DWM jest włączona. Jednak aplikacje korzystające z funkcji Flip Mode Present powinny mieć świadomość ograniczeń podczas korzystania z współbieżnego renderowania interfejsu API GDI.
Istniejące aplikacje można modyfikować, aby korzystać z funkcji Flip Mode Present z tymi samymi korzyściami i zastrzeżeniami co nowo utworzone aplikacje.
Jak wyrazić zgodę na model przerzucania direct3D 9D
Aplikacje Direct3D 9Ex przeznaczone dla systemu Windows 7 mogą zdecydować się na model przerzucania, tworząc łańcuch wymiany z wartością wyliczenia D3DSWAPEFFECT_FLIPEX. Aby wybrać model przerzucania, aplikacje określają strukturę D3DPRESENT_PARAMETERS, a następnie przekazują wskaźnik do tej struktury po wywołaniu interfejsu API IDirect3D9Ex::CreateDeviceEx API. W tej sekcji opisano, w jaki sposób aplikacje przeznaczone dla systemu Windows 7 używają IDirect3D9Ex::CreateDeviceEx, aby wybrać model przerzucania. Aby uzyskać więcej informacji na temat interfejsu API IDirect3D9Ex::CreateDeviceEx, zobacz IDirect3D9Ex::CreateDeviceEx w witrynie MSDN.
Dla wygody składnia D3DPRESENT_PARAMETERS i IDirect3D9Ex::CreateDeviceEx jest powtarzana tutaj.
HRESULT CreateDeviceEx(
UINT Adapter,
D3DDEVTYPE DeviceType,
HWND hFocusWindow,
DWORD BehaviorFlags,
D3DPRESENT_PARAMETERS* pPresentationParameters,
D3DDISPLAYMODEEX *pFullscreenDisplayMode,
IDirect3DDevice9Ex **ppReturnedDeviceInterface
);
typedef struct D3DPRESENT_PARAMETERS {
UINT BackBufferWidth, BackBufferHeight;
D3DFORMAT BackBufferFormat;
UINT BackBufferCount;
D3DMULTISAMPLE_TYPE MultiSampleType;
DWORD MultiSampleQuality;
D3DSWAPEFFECT SwapEffect;
HWND hDeviceWindow;
BOOL Windowed;
BOOL EnableAutoDepthStencil;
D3DFORMAT AutoDepthStencilFormat;
DWORD Flags;
UINT FullScreen_RefreshRateInHz;
UINT PresentationInterval;
} D3DPRESENT_PARAMETERS, *LPD3DPRESENT_PARAMETERS;
Podczas modyfikowania aplikacji Direct3D 9Ex dla systemu Windows 7 w celu wybrania modelu przerzucania należy wziąć pod uwagę następujące elementy dotyczące określonych elementów D3DPRESENT_PARAMETERS:
-
BackBufferCount
-
(Tylko system Windows 7)
Gdy swapEffect jest ustawiona na nowy typ efektu łańcucha wymiany D3DSWAPEFFECT_FLIPEX, liczba wstecznych powinna być równa lub większa niż 2, aby zapobiec karze za wydajność aplikacji w wyniku oczekiwania na poprzedniego bufora obecny do wydania przez dwM.
Gdy aplikacja używa również obecnych statystyk skojarzonych z D3DSWAPEFFECT_FLIPEX, zalecamy ustawienie liczby wstecznych na z zakresu od 2 do 4.
Użycie D3DSWAPEFFECT_FLIPEX w systemie Windows Vista lub wcześniejszych wersjach systemu operacyjnego zakończy się niepowodzeniem z CreateDeviceEx.
-
SwapEffect
-
(Tylko system Windows 7)
Nowy typ efektu D3DSWAPEFFECT_FLIPEX zamiany łańcucha wyznacza, gdy aplikacja przyjmuje tryb przerzucania obecny w usłudze DWM. Umożliwia aplikacji bardziej wydajne użycie pamięci i zasilania, a także umożliwia aplikacji korzystanie z pełnoekranowych statystyk w trybie okna. Nie ma to wpływu na zachowanie aplikacji pełnoekranowej. Jeśli ustawienie Windowed ma wartość true i swapEffect jest ustawiona na D3DSWAPEFFECT_FLIPEX, środowisko uruchomieniowe tworzy jeden dodatkowy bufor wsteczny i obraca dojście, które należy do buforu, który staje się buforem frontu w czasie prezentacji.
-
flagi
-
(Tylko system Windows 7)
Nie można ustawić flagi D3DPRESENTFLAG_LOCKABLE_BACKBUFFER, jeśli SwapEffect jest ustawiona na nowy typ efektu łańcucha wymiany D3DSWAPEFFECT_FLIPEX.
Wytyczne dotyczące projektowania aplikacji modelu flip model Direct3D 9D
Skorzystaj z wytycznych w poniższych sekcjach, aby zaprojektować aplikacje Direct3D 9Ex Flip Model.
Używanie trybu przerzucania obecnego w osobnym HWND z trybu Blt
Aplikacje powinny używać trybu przerzucania Direct3D 9Ex w HWND, który nie jest również przeznaczony dla innych interfejsów API, w tym Blt Mode Present Direct3D 9Ex, innych wersji Direct3D lub GDI. Tryb przerzucania obecny może służyć do prezentowania okna podrzędnego; oznacza to, że aplikacje mogą używać modelu przerzucania, gdy nie jest mieszany z modelem Blt w tym samym HWND, jak pokazano na poniższych ilustracjach.
hwnd
hwnd
Ponieważ model Blt utrzymuje dodatkową kopię powierzchni, GDI i innej zawartości Direct3D można dodać do tego samego HWND za pomocą aktualizacji fragmentacyjnych z Direct3D i GDI. Przy użyciu modelu przerzucania widoczne będą tylko zawartość Direct3D 9Ex w łańcuchach wymiany D3DSWAPEFFECT_FLIPEX przekazywanych do usługi DWM. Wszystkie inne aktualizacje zawartości modelu Blt Direct3D lub GDI zostaną zignorowane, jak pokazano na poniższych ilustracjach.
hwnd
W związku z tym model przerzucania powinien być włączony dla łańcuchowych wymiany powierzchni, w których sam model przerzucania Direct3D 9Ex jest renderowany do całego HWND.
Nie używaj modelu przerzucania z funkcją ScrollWindow lub ScrollWindowEx interfejsu GDI
Niektóre aplikacje Direct3D 9Ex używają funkcji ScrollWindow lub ScrollWindowEx GDI w celu zaktualizowania zawartości okna po wyzwoleniu zdarzenia przewijania użytkownika. ScrollWindow i ScrollWindowEx wykonują blty zawartości okna na ekranie w miarę przewijania okna. Te funkcje wymagają również aktualizacji modelu Blt dla zawartości GDI i Direct3D 9Ex. Aplikacje korzystające z żadnej funkcji niekoniecznie będą wyświetlać widoczną zawartość okna przewijaną na ekranie, gdy aplikacja jest w trybie okna, a usługa DWM jest włączona. Zalecamy, aby w aplikacjach nie używać interfejsów API ScrollWindow i ScrollWindowEx interfejsów API GDI, a zamiast tego ponownie rysować ich zawartość na ekranie w odpowiedzi na przewijanie.
Używanie jednego łańcucha wymiany D3DSWAPEFFECT_FLIPEX na HWND
Aplikacje korzystające z modelu przerzucania nie powinny używać wielu łańcuchów zamian modelu przerzucania modeli przeznaczonych dla tego samego HWND.
Synchronizacja ramek aplikacji modelu przerzucania w trybie Direct3D 9D
Obecne statystyki to informacje o chronometrażu ramek używane przez aplikacje multimedialne do synchronizowania strumieni wideo i audio oraz odzyskiwania po błędach odtwarzania wideo. Aby włączyć dostępność obecnych statystyk, aplikacja Direct3D 9Ex musi upewnić się, że BehaviorFlags parametr, który aplikacja przekazuje do IDirect3D9Ex::CreateDeviceEx zawiera flagę zachowania urządzenia D3DCREATE_ENABLE_PRESENTSTATS.
Dla wygody składnia IDirect3D9Ex::CreateDeviceEx jest powtarzana tutaj.
HRESULT CreateDeviceEx(
UINT Adapter,
D3DDEVTYPE DeviceType,
HWND hFocusWindow,
DWORD BehaviorFlags,
D3DPRESENT_PARAMETERS* pPresentationParameters,
D3DDISPLAYMODEEX *pFullscreenDisplayMode,
IDirect3DDevice9Ex **ppReturnedDeviceInterface
);
Model przerzucania bezpośredniego 3D 9Ex dodaje flagę prezentacji D3DPRESENT_FORCEIMMEDIATE wymuszającą zachowanie D3DPRESENT_INTERVAL_IMMEDIATE flagi prezentacji. Aplikacja Direct3D 9Ex określa te flagi prezentacji w dwFlags parametr, który aplikacja przekazuje do IDirect3DDevice9Ex::P resentEx, jak pokazano poniżej.
HRESULT PresentEx(
CONST RECT *pSourceRect,
CONST RECT *pDestRect,
HWND hDestWindowOverride,
CONST RGNDATA *pDirtyRegion,
DWORD dwFlags
);
Podczas modyfikowania aplikacji Direct3D 9Ex dla systemu Windows 7 należy wziąć pod uwagę następujące informacje o określonych flagach prezentacji D3DPRESENT:
-
Ta flaga jest dostępna tylko w trybie pełnoekranowym lub
(Tylko system Windows 7)
gdy aplikacja ustawia element SwapEffect elementu członkowskiego D3DPRESENT_PARAMETERS, aby D3DSWAPEFFECT_FLIPEX w wywołaniu CreateDeviceEx.
-
(Tylko system Windows 7)
Tę flagę można określić tylko wtedy, gdy aplikacja ustawia element SwapEffect elementu członkowskiego D3DPRESENT_PARAMETERSD3DSWAPEFFECT_FLIPEX w wywołaniu metody CreateDeviceEx. Aplikacja może użyć tej flagi, aby natychmiast zaktualizować powierzchnię z kilkoma ramkami w dalszej części kolejki dwM Present, zasadniczo pomijając ramki pośrednie.
Aplikacje z włączoną funkcją FlipEx mogą używać tej flagi, aby natychmiast zaktualizować powierzchnię ramką, która znajduje się później w kolejce DWM Present, pomijając ramki pośrednie. Jest to szczególnie przydatne w przypadku aplikacji multimedialnych, które chcą odrzucać ramki, które zostały wykryte późno i prezentują kolejne klatki w czasie kompozycji. IDirect3DDevice9Ex::P resentEx zwraca nieprawidłowy błąd parametru, jeśli ta flaga jest niepoprawnie określona.
Aby uzyskać informacje o obecnych statystykach, aplikacja uzyskuje strukturę D3DPRESENTSTATS przez wywołanie interfejsu API IDirect3DSwapChain9Ex::GetPresentStatistics API.
Struktura D3DPRESENTSTATS zawiera statystyki dotyczące wywołań IDirect3DDevice9Ex::P resentEx. Urządzenie musi zostać utworzone przy użyciu wywołania IDirect3D9Ex::CreateDeviceEx z flagą D3DCREATE_ENABLE_PRESENTSTATS. W przeciwnym razie dane zwrócone przez GetPresentStatistics są niezdefiniowane. Łańcuch wymiany Direct3D 9Ex z włączoną funkcją Flip-Model udostępnia informacje statystyczne zarówno w trybach okiennych, jak i pełnoekranowych.
W przypadku łańcuchów wymiany direct3D 9Ex z obsługą modelu Blt-Model w trybie okna wszystkie wartości struktury D3DPRESENTSTATS będą zerami.
W przypadku statystyk obecnych funkcji FlipEx getPresentStatistics zwraca D3DERR_PRESENT_STATISTICS_DISJOINT w następujących sytuacjach:
- Pierwsze wywołanie metody GetPresentStatistics kiedykolwiek, co wskazuje początek sekwencji
- Przejście z funkcji DWM z włączonej do wyłączonej
- Zmiana trybu: tryb okna do lub z pełnoekranowego lub pełnego ekranu do przejść pełnoekranowych
Dla wygody składnia GetPresentStatistics jest powtarzana tutaj.
HRESULT GetPresentStatistics(
D3DPRESENTSTATS * pPresentationStatistics
);
Metoda IDirect3DSwapChain9Ex::GetLastPresentCount zwraca ostatnią metodę PresentCount, czyli identyfikator present ostatniego pomyślnego wywołania Present wykonanego przez urządzenie wyświetlane skojarzone z łańcuchem wymiany. Ten identyfikator obecny to wartość PresentCount składowej struktury D3DPRESENTSTATS. W przypadku łańcuchów wymiany direct3D 9Ex z włączoną obsługą modelu Blt-Model wszystkie wartości struktury D3DPRESENTSTATS będą zerami.
Dla wygody składnia IDirect3DSwapChain9Ex::GetLastPresentCount jest powtarzana tutaj.
HRESULT GetLastPresentCount(
UINT * pLastPresentCount
);
Podczas modyfikowania aplikacji Direct3D 9Ex dla systemu Windows 7 należy wziąć pod uwagę następujące informacje o strukturze D3DPRESENTSTATS:
- Wartość PresentCount, która getLastPresentCount zwraca, nie jest aktualizowana, gdy wywołanie PresentEx z D3DPRESENT_DONOTWAIT określonym w parametrze dwFlags zwraca błąd.
- Po wywołaniu PresentEx z D3DPRESENT_DONOTFLIP wywołanieGetPresentStatistics zakończy się powodzeniem, ale nie zwraca zaktualizowanej struktury D3DPRESENTSTATS, gdy aplikacja jest w trybie okna.
-
PresentRefreshCount a SyncRefreshCount w D3DPRESENTSTATS:
- PresentRefreshCount jest równa SyncRefreshCount, gdy aplikacja jest obecna w każdej funkcji vsync.
- SyncRefreshCount jest uzyskiwany w interwale vsync po przesłaniu obecności, SyncQPCTime jest w przybliżeniu czas skojarzony z interwałem vsync.
typedef struct _D3DPRESENTSTATS {
UINT PresentCount;
UINT PresentRefreshCount;
UINT SyncRefreshCount;
LARGE_INTEGER SyncQPCTime;
LARGE_INTEGER SyncGPUTime;
} D3DPRESENTSTATS;
Synchronizacja ramek dla aplikacji okiennych, gdy usługa DWM jest wyłączona
Gdy usługa DWM jest wyłączona, aplikacje okienne są wyświetlane bezpośrednio na ekranie monitora bez przechodzenia przez łańcuch przerzucania. W systemie Windows Vista nie ma obsługi uzyskiwania informacji o statystykach ramek dla aplikacji okiennych, gdy usługa DWM jest wyłączona. Aby zachować interfejs API, w którym aplikacje nie muszą być świadome dwM, system Windows 7 zwróci informacje statystyczne dotyczące ramek dla aplikacji okiennych, gdy usługa DWM jest wyłączona. Statystyki ramki zwracane, gdy funkcja DWM jest wyłączona, są tylko szacowane.
Walk-Through modelu przerzucania direct3D 9Ex i przykładu przedstawiania statystyk
Aby wybrać prezentację FlipEx dla przykładu Direct3D 9Ex
- Upewnij się, że przykładowa aplikacja jest uruchomiona w systemie operacyjnym Windows 7 lub nowszym.
- Ustaw element członkowski D3DPRESENT_PARAMETERSSwapEffectD3DPRESENT_PARAMETERS na D3DSWAPEFFECT_FLIPEX wywołania CreateDeviceEx.
OSVERSIONINFO version;
ZeroMemory(&version, sizeof(version));
version.dwOSVersionInfoSize = sizeof(version);
GetVersionEx(&version);
// Sample would run only on Win7 or higher
// Flip Model present and its associated present statistics behavior are only available on Windows 7 or higher operating system
bool bIsWin7 = (version.dwMajorVersion > 6) ||
((version.dwMajorVersion == 6) && (version.dwMinorVersion >= 1));
if (!bIsWin7)
{
MessageBox(NULL, L"This sample requires Windows 7 or higher", NULL, MB_OK);
return 0;
}
, aby również wyrazić zgodę na korzystanie z przykładu FlipEx skojarzonego ze statystyką bieżącą dla przykładu Direct3D 9Ex
- Ustaw D3DCREATE_ENABLE_PRESENTSTATS w parametrze BehaviorFlagsCreateDeviceEx.
// Set up the structure used to create the D3DDevice
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIPEX; // Opts into Flip Model present for D3D9Ex swapchain
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = 256;
d3dpp.BackBufferHeight = 256;
d3dpp.BackBufferCount = QUEUE_SIZE;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
g_iWidth = d3dpp.BackBufferWidth;
g_iHeight = d3dpp.BackBufferHeight;
// Create the D3DDevice with present statistics enabled - set D3DCREATE_ENABLE_PRESENTSTATS for behaviorFlags parameter
if(FAILED(g_pD3D->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_ENABLE_PRESENTSTATS,
&d3dpp, NULL, &g_pd3dDevice)))
{
return E_FAIL;
}
Aby uniknąć, wykrywanie i odzyskiwanie po
Wywołania obecne w kolejce: zalecana liczba backbuffer wynosi od 2 do 4.
Przykład Direct3D 9Ex dodaje niejawną backbuffer, rzeczywista długość kolejki obecnej to liczba backbuffer + 1.
Utwórz strukturę kolejki prezentera, aby zapisać wszystkie pomyślnie przesłane identyfikatory prezentu (PresentCount) i skojarzone, obliczone/oczekiwane elementy PresentRefreshCount.
Aby wykryć wystąpienie usterki:
- Wywołaj GetPresentStatistics.
- Pobierz identyfikator prezentu (PresentCount) i liczbę vsync, w której jest wyświetlana ramka (PresentRefreshCount) ramki, której obecne statystyki są uzyskiwane.
- Pobierz oczekiwany element PresentRefreshCount (TargetRefresh w przykładowym kodzie) skojarzony z identyfikatorem prezentu.
- Jeśli rzeczywista wartość PresentRefreshCount jest późniejsza niż oczekiwana, wystąpiła usterki.
Aby odzyskać po usterki:
- Oblicz liczbę ramek do pominięcia (g_ zmienną iImmediates w przykładowym kodzie).
- Przedstawia pominięte ramki z interwałem D3DPRESENT_FORCEIMMEDIATE.
Zagadnienia dotyczące wykrywania i odzyskiwania po awarii
Odzyskiwanie usterki przyjmuje N (zmienna g_iQueueDelay w przykładowym kodzie) liczby wywołań obecnych, w których N (g_iQueueDelay) równa g_iImmediates plus długość kolejki Present, czyli:
- Pomijanie ramek z D3DPRESENT_FORCEIMMEDIATE interwału Present oraz
- Prezenty w kolejce, które należy przetworzyć
Ustaw limit długości usterki (GLITCH_RECOVERY_LIMIT w próbce). Jeśli przykładowa aplikacja nie może odzyskać sprawności po usterce, która jest zbyt długa (oznacza to, że 1 sekunda lub 60 asynchronicznych na monitorze 60Hz), przeskocz sporadycznie animację i zresetuj kolejkę pomocnika Prezent.
VOID Render()
{
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
g_pd3dDevice->BeginScene();
// Compute new animation parameters for time and frame based animations
// Time-based is a difference between base and current SyncRefreshCount
g_aTimeBasedHistory[g_iBlurHistoryCounter] = g_iStartFrame + g_LastSyncRefreshCount - g_SyncRefreshCount;
// Frame-based is incrementing frame value
g_aFrameBasedHistory[g_iBlurHistoryCounter] = g_iStartFrame + g_iFrameNumber;
RenderBlurredMesh(TRUE); // Time-based
RenderBlurredMesh(FALSE); // Frame-based
g_iBlurHistoryCounter = (g_iBlurHistoryCounter + 1) % BLUR_FRAMES;
DrawText();
g_pd3dDevice->EndScene();
// Performs glitch recovery if glitch was detected
if (g_bGlitchRecovery && (g_iImmediates > 0))
{
// If we have present immediates queued as a result of glitch detected, issue forceimmediate Presents for glitch recovery
g_pd3dDevice->PresentEx(NULL, NULL, NULL, NULL, D3DPRESENT_FORCEIMMEDIATE);
g_iImmediates--;
g_iShowingGlitchRecovery = MESSAGE_SHOW;
}
// Otherwise, Present normally
else
{
g_pd3dDevice->PresentEx(NULL, NULL, NULL, NULL, 0);
}
// Add to helper Present queue: PresentID + expected present refresh count of last submitted Present
UINT PresentCount;
g_pd3dSwapChain->GetLastPresentCount(&PresentCount);
g_Queue.QueueFrame(PresentCount, g_TargetRefreshCount);
// QueueDelay specifies # Present calls to be processed before another glitch recovery attempt
if (g_iQueueDelay > 0)
{
g_iQueueDelay--;
}
if (g_bGlitchRecovery)
{
// Additional DONOTFLIP presents for frame conversions, which basically follows the same logic, but without rendering
for (DWORD i = 0; i < g_iDoNotFlipNum; i++)
{
if (g_TargetRefreshCount != -1)
{
g_TargetRefreshCount++;
g_iFrameNumber++;
g_aTimeBasedHistory[g_iBlurHistoryCounter] = g_iStartFrame + g_LastSyncRefreshCount - g_SyncRefreshCount;
g_aFrameBasedHistory[g_iBlurHistoryCounter] = g_iStartFrame + g_iFrameNumber;
g_iBlurHistoryCounter = (g_iBlurHistoryCounter + 1) % BLUR_FRAMES;
}
if (g_iImmediates > 0)
{
g_pd3dDevice->PresentEx(NULL, NULL, NULL, NULL, D3DPRESENT_FORCEIMMEDIATE | D3DPRESENT_DONOTFLIP);
g_iImmediates--;
}
else
{
g_pd3dDevice->PresentEx(NULL, NULL, NULL, NULL, D3DPRESENT_DONOTFLIP);
}
UINT PresentCount;
g_pd3dSwapChain->GetLastPresentCount(&PresentCount);
g_Queue.QueueFrame(PresentCount, g_TargetRefreshCount);
if (g_iQueueDelay > 0)
{
g_iQueueDelay--;
}
}
}
// Check Present Stats info for glitch detection
D3DPRESENTSTATS PresentStats;
// Obtain present statistics information for successfully displayed presents
HRESULT hr = g_pd3dSwapChain->GetPresentStats(&PresentStats);
if (SUCCEEDED(hr))
{
// Time-based update
g_LastSyncRefreshCount = PresentStats.SyncRefreshCount;
if ((g_SyncRefreshCount == -1) && (PresentStats.PresentCount != 0))
{
// First time SyncRefreshCount is reported, use it as base
g_SyncRefreshCount = PresentStats.SyncRefreshCount;
}
// Fetch frame from the queue...
UINT TargetRefresh = g_Queue.DequeueFrame(PresentStats.PresentCount);
// If PresentStats returned a really old frame that we no longer have in the queue, just don't do any glitch detection
if (TargetRefresh == FRAME_NOT_FOUND)
return;
if (g_TargetRefreshCount == -1)
{
// This is first time issued frame is confirmed by present stats, so fill target refresh count for all frames in the queue
g_TargetRefreshCount = g_Queue.FillRefreshCounts(PresentStats.PresentCount, g_SyncRefreshCount);
}
else
{
g_TargetRefreshCount++;
g_iFrameNumber++;
// To determine whether we're glitching, see if our estimated refresh count is confirmed
// if the frame is displayed later than the expected vsync count
if (TargetRefresh < PresentStats.PresentRefreshCount)
{
// then, glitch is detected!
// If glitch is too big, don't bother recovering from it, just jump animation
if ((PresentStats.PresentRefreshCount - TargetRefresh) > GLITCH_RECOVERY_LIMIT)
{
g_iStartFrame += PresentStats.SyncRefreshCount - g_SyncRefreshCount;
ResetAnimation();
if (g_bGlitchRecovery)
g_iGlitchesInaRow++;
}
// Otherwise, compute number of immediate presents to recover from it -- if we?re not still trying to recover from another glitch
else if (g_iQueueDelay == 0)
{
// skip frames to catch up to expected refresh count
g_iImmediates = PresentStats.PresentRefreshCount - TargetRefresh;
// QueueDelay specifies # Present calls before another glitch recovery
g_iQueueDelay = g_iImmediates + QUEUE_SIZE;
if (g_bGlitchRecovery)
g_iGlitchesInaRow++;
}
}
else
{
// No glitch, reset glitch count
g_iGlitchesInaRow = 0;
}
}
}
else if (hr == D3DERR_PRESENT_STATISTICS_DISJOINT)
{
// D3DERR_PRESENT_STATISTICS_DISJOINT means measurements should be started from the scratch (could be caused by mode change or DWM on/off transition)
ResetAnimation();
}
// If we got too many glitches in a row, reduce framerate conversion factor (that is, render less frames)
if (g_iGlitchesInaRow == FRAMECONVERSION_GLITCH_LIMIT)
{
if (g_iDoNotFlipNum < FRAMECONVERSION_LIMIT)
{
g_iDoNotFlipNum++;
}
g_iGlitchesInaRow = 0;
g_iShowingDoNotFlipBump = MESSAGE_SHOW;
}
}
przykładowy scenariusz
Poniższa ilustracja przedstawia aplikację z liczbą backbuffer 4. Rzeczywista długość kolejki obecnej wynosi zatem 5.
kolejkiRamka A jest przeznaczona do przejścia na ekranie w interwałach synchronizacji 1, ale wykryto, że był wyświetlany w interwałach synchronizacji 4. W związku z tym wystąpiła usterki. Kolejne 3 klatki są prezentowane z D3DPRESENT_INTERVAL_FORCEIMMEDIATE. Usterki powinny przyjmować łącznie 8 wywołań obecnych przed odzyskaniem — następna ramka będzie wyświetlana zgodnie z docelową liczbą interwałów synchronizacji.
Podsumowanie zaleceń dotyczących programowania dotyczących synchronizacji ramek
Utwórz listę kopii zapasowych wszystkich identyfikatorów LastPresentCount (uzyskanych za pośrednictwem GetLastPresentCount) i skojarzonych szacowanych identyfikatorów PresentRefreshCount wszystkich przesłanych prezentów.
Nuta
Gdy aplikacja wywołuje PresentEx z D3DPRESENT_DONOTFLIP, wywołanie GetPresentStatistics zakończy się pomyślnie, ale nie zwróci zaktualizowanej struktury D3DPRESENTSTATS, gdy aplikacja jest w trybie okna.
Wywołaj GetPresentStatistics, aby uzyskać rzeczywisty element PresentRefreshCount skojarzony z każdym wyświetlonym identyfikatorem prezentu ramek, aby upewnić się, że aplikacja obsługuje błędy zwracane z wywołania.
Jeśli rzeczywista wartość PresentRefreshCount jest późniejsza niż szacowana wartość PresentRefreshCount, zostanie wykryta usterki. Kompensuj przez przesłanie ramek opóźnionych z D3DPRESENT_FORCEIMMEDIATE.
Gdy jedna ramka zostanie wyświetlona pod koniec kolejki Obecne, wszystkie kolejne ramki w kolejce będą wyświetlane późno. D3DPRESENT_FORCEIMMEDIATE poprawi tylko następną ramkę, która zostanie wyświetlona po wszystkich ramkach w kolejce. W związku z tym liczba obecnych kolejek lub backbuffer nie powinna być zbyt długa — więc istnieje mniej błędów ramek, aby nadrobić zaległości. Optymalna liczba backbuffer wynosi od 2 do 4.
Jeśli szacowana wartość PresentRefreshCount jest późniejsza niż rzeczywista wartość PresentRefreshCount, może wystąpić ograniczanie dwM. Możliwe są następujące rozwiązania:
- zmniejszenie długości kolejki obecnej
- zmniejszenie wymagań dotyczących pamięci procesora GPU przy użyciu innych środków oprócz zmniejszenia długości kolejki obecnej (czyli zmniejszania jakości, usuwania efektów itd.)
- określanie dwmEnableMMCSS w celu ogólnego ograniczenia przepustowości dwM
Sprawdź funkcjonalność wyświetlania aplikacji i wydajność statystyk ramek w następujących scenariuszach:
- z włączonym i wyłączonym modułem DWM
- tryby wykluczania i okna pełnoekranowego
- sprzęt niższej możliwości
Gdy aplikacje nie mogą odzyskać sprawności po dużej liczbie usterki ramek z D3DPRESENT_FORCEIMMEDIATE Present, mogą one potencjalnie wykonać następujące operacje:
- zmniejsz użycie procesora CPU i procesora GPU przez renderowanie przy mniejszym obciążeniu.
- w przypadku dekodowania wideo dekoduj szybciej, zmniejszając jakość, a tym samym użycie procesora CPU i procesora GPU.
Wnioski dotyczące ulepszeń funkcji Direct3D 9Ex
W systemie Windows 7 aplikacje, które wyświetlają częstotliwość klatek wideo lub mierników podczas prezentacji, mogą zdecydować się na przerzucanie modelu. Obecne ulepszenia statystyk skojarzone z funkcją Flip Model Direct3D 9Ex mogą przynieść korzyści aplikacjom, które synchronizują prezentację z szybkością klatek w czasie rzeczywistym z opiniami dotyczącymi wykrywania i odzyskiwania w czasie rzeczywistym. Deweloperzy, którzy przyjmują model przerzucania bezpośredniego 3D 9Ex, powinni wziąć pod uwagę osobną wartość HWND od synchronizacji szybkości klatek i zawartości GDI. Zapoznaj się ze szczegółami w tym temacie. Aby uzyskać dodatkową dokumentację, zobacz centrum deweloperów DirectX w witrynie MSDN.
Wywołanie akcji
Zachęcamy do korzystania z modelu Flip w trybie Direct3D 9D i jego obecnych statystyk w systemie Windows 7 podczas tworzenia aplikacji, które próbują zsynchronizować częstotliwość ramki prezentacji lub odzyskać dane po błędach wyświetlania.
Tematy pokrewne
Centrum deweloperów DirectX w witrynie MSDN