2012-02-24 17 views
9

Testowałem swoją grę na iOS i zauważyłem rozbieżność pomiędzy ilością zajmowanej pamięci i ilością, jaką powinna ona podjąć. W końcu zawęziłem problem do tekstur, zabierając o 33% więcej pamięci, niż myślałem.Tekstury iOS Pobieranie 33% dodatkowej pamięci

Na przykład, wydaje mi się, że nieskompresowana 32-bitowa tekstura 256x256 powinna zająć 256 * 256 * 4 bajty = 256k. Jednak zauważyłem, że pamięć aplikacji rośnie o 340k przy przydzielaniu tekstury 256x256. To było tak, jakby urządzenie przydzielało wystarczającą ilość pamięci do przechowywania tekstury i wszystkich jej mipmap, ale nie używam map mipa ani nie pytam o przestrzeń w żaden sposób.

Ta dodatkowa pamięć wyróżniała się, ponieważ miała miejsce tylko na niektórych urządzeniach. Zauważyłem dodatkowej pamięci podczas testowania gry na iPod Touch 4. Jednak problem nie występuje na iPhone 3GS, iPod lub iPad 3G 1.

Wersje systemu na urządzeniach są:

iPod 3G - iOS 3.1.2 (7D11) iPhone 3GS - iOS 4.3.5 (8L1) iPod 4 - iOS 4.2.1 (8C148) iPad - iOS 4.3 (8F190)

EDIT

Oto trochę więcej informacji. Zmierzam pamięć aplikacji w ten sposób, tak jak ta

int PlatformIOS::GetProcessMemUsage() 
{ 
    task_basic_info info; 
    mach_msg_type_number_t size = sizeof(info); 
    kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size); 
    if (kerr == KERN_SUCCESS) 
     return info.resident_size; 

    return 0; 
} 

Zwraca tę samą wartość, którą zobaczysz w programie Insturments dla Real Mem. Jest to bardzo przydatne.

A oto jak ja przeznaczyć moje tekstur:

bool GL3DTextureDataPiece::CreateTextureSurface(X3DInterfaceImpl *theInterface, int theWidth, int theHeight, PixelFormat theFormat, RefCount *thePalette, bool generateMipMap) 
{ 
    glGenTextures(1,&mTexture); 
    theInterface->SetCurTexture(this); 

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,mLinearFilter?GL_LINEAR:GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,mLinearFilter?GL_LINEAR:GL_NEAREST); 

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, theWidth, theHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 

    return true; 
} 

To wszystko jest bardzo proste rzeczy. Jedyną rzeczą, która doprowadziła mnie do znalezienia problemów z pamięcią w pierwszej kolejności, była rozbieżność między różnymi urządzeniami. W rzeczywistości była to rozbieżność pomiędzy całkowitą pamięcią aplikacji i pamięcią zasobów (sam śledziłem obrazy i pamięć dźwiękową), które skłoniły mnie do zbadania, aby znaleźć ten błąd.

+0

Oczywiście, że nie dotyczy to kodu efektu, ale zastanawiam się, czy ma to coś wspólnego z wyświetlaczem Retina? – summea

+0

Jak mierzysz pamięć aplikacji? – Justicle

Odpowiedz

8

Już znalazłem obejście, więc odpowiem na własne pytanie. Ale myślałem, że to opublikuję, ponieważ wydaje się, że jest to ważna informacja, o której trzeba pamiętać.

Inne osoby znalazły ten błąd. Na przykład, zobacz tutaj:

http://www.cocos2d-iphone.org/forum/topic/29121

Dobrą wiadomością jest to, że istnieje obejście błędu. Obejście tego problemu polega na używaniu tylko tekstur o braku mocy (npot). Teksty NPOT nie mogą być mapowane mipem, więc iOS nie próbuje przydzielić dodatkowej pamięci map (przynajmniej taka jest ich teoria).

Na szczęście było to łatwe do zrobienia w moim silniku, ponieważ już dzieli obrazy na wiele tekstur, jeśli to konieczne, aby dopasować się do tekstury potęgi-2 bez użycia zbyt dużej ilości pamięci. Po prostu zmodyfikowałem kod, aby nie dzielić obrazów, aby pasowały do ​​tekstur o sile 2, a ponadto wymusić na obrazie, który byłby potęgą 2 w obu wymiarach, aby załadować teksturę o 1 piksel większą niż konieczne w szerokości. Na przykład umieściłbym obrazek 256x256 w teksturach 257x256.

Wyeliminowało to dodatkowy wzrost pamięci o 33%.

Należy pamiętać, że starsze urządzenia, takie jak iPod 3G, nie mogą tworzyć tekstur npot, dlatego ważne jest sprawdzenie, czy jest to możliwe przed wykonaniem tej poprawki. Aby to sprawdzić, możesz wysłać zapytanie do rozszerzenia GL_APPLE_texture_2D_limited_npot. Należy również uważać, aby nie przekroczyć maksymalnego rozmiaru tekstury dodając ten dodatkowy piksel, aby wymusić na fakturze teksturę.

+0

Próbowałem zaakceptować odpowiedź, ale musisz poczekać 2 dni, zanim to zrobisz. To właściwie ma sens. Wtedy może ktoś będzie miał lepszą odpowiedź. –

+0

Wystarczająco uczciwe :) – jrtc27

4

upewnij się, że nie jesteś automatycznie generując mipmaps: http://www.opengl.org/wiki/Texture#Automatic_mipmap_generation

Łańcuch mipmapa wezmą 33% dodatkowej przestrzeni, jak łańcuch mipmapa zbliżona 1/3 extra - patrz poniżej serii gdzie t jest wielkość oryginalna struktura: = t + t/4 + t/16 t +/64 itd ...

EDIT:

Uwaga byłoby również pomocne odpowiedzieć metody użyte do pomiaru pamięć aplikacji i jakiej metody użyłeś do stworzenia tekstury.

Może być tak, że użyta metoda zawsze tworzy dodatkowy 33% bufor lub może po prostu wywołać metodę niepoprawnie.

+0

To zabawne, ponieważ natknąłem się na ten dokładny link i pomyślałem, że może w jakiś sposób powstają automatycznie mipmapy, ale tak naprawdę trzeba zadzwonić do glGenerateMipmap, żeby to się stało, a ja tego nie nazywam. –

Powiązane problemy