Jedną z rzeczy, która na początku programowania w DirectX może wydawać się dziwna, jest tajemniczy parametr Pool
. Pojawia się on w każdej funkcji, która tworzy jakiś zasób graficzny: teksturę, bufor wierzchołków, siatkę modelu (ID3DXMesh
), bufor głębokości, itp.
Rolą tego parametru jest określenie, w której puli pamięci znajdzie się tworzony zasób. DX wyróżnia bowiem ich kilka, co jest związane przede wszystkim z (przynajmniej) dwoma rodzajami pamięci, z jakimi możemy mieć do czynienia programując grafikę: zwykłym systemowym RAM-em oraz pamięcią karty graficznej.
W jakiej puli powinniśmy więc umieszczać swoje obiekty? To zależy od kilku czynników. Na początek na pewno warto przyjrzeć możliwościom:
D3DPOOL_DEFAULT
, jak wskazuje na to nazwa, oznacza pulę domyślną. Gdy użyjemy tej flagi, DirectX umieści nasz zasób w najlepszym – pod względem wydajności – miejscu, bazując przy tym na innym parametrze, Usage
(określa on, mówiąc w skrócie, sposób wykorzystania danego zasobu). Tym najlepszym miejscem jest prawie zawsze pamięć karty graficznej.D3DUSAGE_DYNAMIC
), ich blokowanie wiąże się ze stratą szybkości albo jest wręcz niemożliwe (w przypadku tekstur).D3DPOOL_MANAGED
to pula zarządzana. Oznacza to, że pieczę nad nią sprawują sam DirectX i to on decyduje, w którym rodzaju pamięci zasoby z tej puli zostaną umieszczone. Zazwyczaj oznacza to, że w pamięci operacyjnej trzymana jest kopia obiektu, znajdującego się też w pamięci graficznej. Dzięki temu nie trzeba go tworzyć ponownie w przypadku straty urządzenia, a także można go blokować i modyfikować niezależnie od typu i flag Usage
; w tym przypadku DX zadba o odpowiednią synchronizację.D3DPOOL_SYSTEMMEM
oznacza pulę pamięci systemowej. Zasoby tu stworzone będą znajdowały się w zwykłym RAM-ie i nie będą mogły być bezpośrednio renderowane. Dane z nich mogą jednak być kopiowane do zasobów znajdujących się w puli domyślnej, jak chociażby poprzez funkcję UpdateTexture
.D3DPOOL_SCRATCH
jest również usytuowana w pamięci systemowej (RAM). W odróżnieniu od poprzedniej, zasoby z tej puli nie są jednak w żaden sposób (także pośredni) dostępne dla urządzenia i nie mogą być używane podczas renderowania. Oznacza to też, że nie podlegają one ograniczeniom związanym z kartą graficzną. Można więc, przykładowo, tworzyć w tej puli tekstury o rozmiarach niebędących potęgami dwójki także wtedy, gdy karta nie wspiera takich tekstur.Spotkałem się z dwiema ogólnymi wytycznymi dotyczącymi tego, z których pul pamięci należy korzystać:
D3DPOOL_DEFAULT
, bo to zapewnia największą wydajność, jako że wtedy zasoby generalnie umieszczane są w pamięci karty graficznej.D3DPOOL_MANAGED
, gdyż wtedy pozwalamy DirectX-owi zdecydować, w jakim rodzaju pamięci trzymać nasz zasób – a już on powinien o tym wiedzieć lepiej.W sumie więc wygląda na to, że nic nie wiadomo :) Oczywiście są przypadki, gdy wyboru nie mamy, jak to się dzieje choćby dla tekstur typu render target, które muszą być stworzone w D3DPOOL_DEFAULT
. Zawsze jednak będziemy mieli takie zasoby, które “równie dobrze” dałoby się umieścić w puli domyślnej, jak i zarządzanej. Co wtedy?
Otóż wydaje mi się, że to zależy od wielkości naszej aplikacji (w sensie rozmiaru używanych zasobów) oraz… stopnia zaawansowania w programowaniu w DirectX. Na początek bowiem D3DPOOL_MANAGED
jest pulą bezpieczniejszą: nie musimy się w niej martwić o stratę urządzenia i możemy każdy zasób blokować i zmieniać. Ceną za to jest wzrost zużycia pamięci przez aplikację, spowodowany trzymaniem przez DX kopii obiektów w pamięci systemowej.
Jeśli jednak nasza gra (nie bójmy się użyć tego słowa ;)) używa dużej ilości zasobów, to takie marnotrawstwo jest zwykle nie do przyjęcia. Wtedy przynajmniej część z nich należy przenieść do D3DPOOL_DEFAULT
. Istnieje szansa, że na tym etapie będziemy już wiedzieć lepiej, którą część ;-)
Na koniec pozwolę sobie też wspomnieć o – często pomijanej – puli D3DPOOL_SCRATCH
. Jej przeznaczeniem są wszelkiego rodzaju zasoby pomocnicze, których nie renderujemy, ale mimo to wykorzystujemy do jakiegoś celu – na przykład tworzenia innych zasobów. Typowym przykładem są wszelkiego rodzaju pomocnicze, narzędziowe tekstury – jak choćby mapy wysokości (heightmap), na podstawie których generujemy ukształtowanie terenu.
Najlepszą pulą dla takich obiektów jest właśnie D3DPOOL_SCRATCH
. Użycie jakiejkolwiek innej spowodowałoby uszczerbek na wydajności lub wręcz błędy, jak np. niezamierzone przeskalowanie tekstury do rozmiaru 2n.
Dzięki za fajną notkę. W ostatnim akapicie jest pomyłka, miało być zapewne “wszelkiego rodzaju zasoby pomocnicze, których nie renderujemy”.
Istotnie. Poprawione :)