Przez lata swej aktywności publicystycznej, jak i tej na forach o tematyce komputerowo-growej wielokrotnie dane mi się było spotkać z terminem "optymalizacja", któremu nader często, szczególnie w przypadku konsol, towarzyszyły jeszcze enigmatyczne stwierdzenia o wyciskaniu ukrytej mocy ze sprzętu. Cóż, z pozoru wszystko tutaj wygląda na oczywiste. Jeśli jakaś produkcja chodzi niedostatecznie dobrze na wydawałoby się mocnym sprzęcie, to mówimy właśnie o kiepskiej optymalizacji. Analogicznie, oglądanie takich produkcji jak The Last of Us czy Beyond: Two Souls na bagatela siedmioletnim wówczas PlayStation 3 mogło robić wrażenie, a po zestawieniu z pierwszymi tytułami na tę platformę wręcz szokować. Summa summarum wykreowanych zostają setki obiegowych mitów, frazesów będących często zbyt daleko idącymi uproszczeniami, które tyleż często prowadzą do bezzasadnego kamienowania deweloperów, co są przyczyną pisania im, nie bójmy się tego słowa, absurdalnych peanów. Zastanówmy się więc, jak to naprawdę jest z tą mityczną optymalizacją.
Studnia bez dna? Niekoniecznie
Zacznijmy od tego, że żaden hardware nie jest przysłowiową studnią bez dna. Obojętnie, czy mamy na myśli dowolną konsolę, czy może wysokowydajny PC-et z procesorem Intel Core i7 i kartą grafiki Nvidia GeForce GTX 1080 Ti. Deweloper zawsze otrzymuje na blat pewien budżet na obliczenia, w którym bezwzględnie musi się zmieścić. Co oczywiste, w przypadku urządzeń o zamkniętej architekturze jest to konkretny skalar, a tworząc gry dla komputerów osobistych należy podejść do sprawy bardziej szacunkowo. Tym niemniej moc poszczególnych platform, rozumiana poprzez sprawność w obliczeniach arytmetycznych czy wsparcie dla konkretnych instrukcji, zawsze jest ograniczona. Wprawdzie można pozwolić sobie na niewielką manipulację, jak niegdyś zrobiło Sony podnosząc poprzez oprogramowanie układowe taktowanie procesora w PlayStation Portable do 333 MHz, ale tu już pojawia się kwestia ingerencji w sprzęt, której producent gry autonomicznie przeprowadzić nie może.
PSP - konsola, w której swego czasu podkręcono procesor przez firmware
Tak czy inaczej, żaden układ elektroniczny nie zwiększy samoczynnie swojej efektywności - procesor nie wykona większej liczby operacji na cykl zegara, pojemność pamięci nie wzrośnie, a karta graficzna nie narysuje obiektów ponad sprecyzowane możliwości. Najprościej zobrazować to na przykładzie naczynia z wodą o określonej pojemności. W normalnych warunkach nie wlejemy do niego więcej cieczy niż przewidział producent. Nie i koniec. Tym samym o pokładach ukrytej mocy obliczeniowej możemy mówić tylko wtedy, gdy twórca sprzętu - jakkolwiek to zabawnie nie brzmi - faktycznie je ukryje. Jak, zapytacie? Ano, chociażby przez zablokowanie i późniejsze uwolnienie poprzez firmware części jednostek wykonawczych. Tak zrobił chociażby Microsoft, odcinając 128 procesorów strumieniowych Xboksa One na wyłączne potrzeby sensora Kinect, a następnie udostępniając je wszystkim twórcom w aktualizacji devkitu. Wtedy też, nawiasem mówiąc, po tytułach startowych działających w rozdzielczości 720p zaczęły wysypywać się produkcje celujące w 900p.
Diabeł tkwi w kodzie
Odrębną kwestię stanowi wykorzystanie sprzętu, a właściwie zdolność programistów do zarządzania tym, co otrzymali na ręce. Wróćmy do wspomnianej w pierwszym akapicie konsoli PlayStation 3. Jak pamiętamy, sprzęt ten dysponuje niezwykle nietypowym procesorem Cell od IBM, w którym główny rdzeń PowerPC (PPE) koordynuje pracę sześciu koprocesorów wektorowych (SPE), mogących przeprowadzić łącznie nawet 96 operacji na 8-bitowych liczbach całkowitych w cyklu zegara. Zdolność Cella do wykonywania dziesiątek prostych obliczeń swego czasu skłoniła programistów z Naughty Dog, odpowiedzialnych m.in. za serię Uncharted i już wcześniej wywołane The Last of Us, do przerzucenia efektów postprodukcyjnych z niedomagającego układu graficznego RSX na procesor, co pozwoliło sumarycznie podnieść jakość grafiki. Ponoć imponująca na tamte czasy głębia ostrości w Uncharted 2 została uzyskana właśnie tym sposobem, a programiści mogli rozbudować m.in. geometrię scen i oświetlenie, czyli efekty będące już kompletnie typowymi zadaniami karty graficznej.
Procesor Cell, alternatywnie zwany koszmarem programistów
Sztuczki - niemagiczki
Ale gospodarowanie zasobami to tylko jedna strona medalu. Dodatkowo, dostępna jedynie w przypadku zamkniętych i dobrze opisanych architektur. Tu warto raz jeszcze przytoczyć przykład naczynia na określoną ilość cieczy, do którego możemy wlać zwykłą wodę, ale także zdecydowanie smaczniejszy sok. W grafice komputerowej chodzi bowiem o to, by zapewnić odbiorcy atrakcyjne doznania, a nie osiągnąć bezwzględną doskonałość. Dlatego też powszechnie stosuje się ogromny wachlarz różnorakich sztuczek, przez co optymalizacja staje się tak naprawdę optycznym oszustwem. Pod tym względem prym wiedzie efekt poziomu szczegółów (ang. level of detail), które intencjonalnie zmniejsza się dla obiektów umieszczonych w oddali i / lub na krawędziach ekranu, na które gracz siłą rzeczy zwraca mniejszą uwagę. Przykładowo, w Super Mario Odyssey na Nintendo Switch najdalsze widzowi obiekty podmieniane są na prościutkie, dwuwymiarowe sprite'y.
Tak, to naprawdę potrafi Tegra X1, ale nic za darmo...
Idąc dalej, warto zwrócić uwagę na rozmycie obrazu w ruchu (ang. motion blur). Twórcy bardzo chętnie wykorzystują ten efekt, by dodać grze pozornej dynamiki, maskując przy tym słabostki obiektów dookoła, np. otoczenia torów w przypadku wyścigów samochodowych, co często widać chociażby w tytułach z serii Need for Speed. Ciekawostką jest fakt, iż agresywne rozmycie "upłynnia" konsolowe gry w 30 kl./s. Jakiś czas temu narodziła się też moda na wszelkiej maści filtry postprodukcyjne - bloom, nakładanie ziarna kliszy fotograficznej, abberację chromatyczną, manipulowanie gammą. To oczywiście również zabiegi o charakterze optymalizacyjnym. Sztuczki tego typu mają przeważnie ledwie symboliczny koszt sprzętowy, a pozwalają uczynić rozgrywkę zdecydowanie bardziej efektowną, przynajmniej na pierwszy rzut oka. Oczywiście nie należy zapominać o samej architekturze gameplay'u. Klaustrofobiczne korytarze zawsze będą wyglądać lepiej od otwartych światów. A wszystko wynika ze zdecydowanie niższej złożoności tych pierwszych.
Druga strona medalu
Co ciekawe, jak to w życiu bywa, trafiają się też przykłady celowej "anty-optymalizacji". Najbardziej znamiennym jest wydany w 2011 roku Crysis 2, który w trybie DirectX 11 dodawał efekt teselacji do wody znajdującej się pod mapą i niewidocznej dla gracza. Ówczesne karty GeForce osiągały miażdżącą przewagę nad Radeonami przy przetwarzaniu złożonej geometrii. Wniosek niech każdy wyciągnie sam. Niekiedy dzieje się również tak, że twórcy muszą celowo pociąć kod w jakichś aspektach, by zaspokoić potrzeby rynku i zwiększyć grono odbiorców swej produkcji. Assassin's Creed Unity ma w pełni dynamiczne oświetlenie i tętniące życiem ulice Paryża z ogromną liczbą NPC. Oba kolejne wydania, Syndicate oraz Origins, literalnie skiepszczono pod tymi względami, by zadowolić posiadaczy konsol oraz słabszych konfiguracji sprzętowych - efekty świetlne są w wielu przypadkach prerenderowane, a liczba NPC została drastycznie zredukowana. Z pewnością nie sprzyja to rozwojowi. No, ale gra musi na siebie zarobić, a żeby tak się stało odbiorcy muszą być zadowoleni z jej działania.
W przypadku Crysis 2 pogląd na optymalizację okazał się nieco inny ;)
Wulkany i inne takie
Pozwolę sobie jeszcze poświęcić akapit na afiszowane środowiska programistyczne, Vulkan oraz DirectX 12, które wedle zapowiedzi miały pozwolić na spektakularne skoki wydajności, a zwłaszcza w przypadku tego drugiego skończyło się to raczej mało widowiskowo. Środowisko programistyczne, tak samo jak każdy inny czynnik, mocy sprzętu nie zwiększy. Atutem tych konkretnych miało być dopuszczenie tzw. instrukcji niskiego poziomu, a więc poleceń wydawanych karcie graficznej maszynowo, niewymagających translacji poprzez sterownik. Tym sposobem próbowano uwolnić zasoby procesora okupowane wyjściowo tłumaczeniem poleceń. Niestety kod maszynowy ma do siebie to, że musi powstawać wyłącznie z myślą o jednym jedynym sprzęcie, albo przynajmniej wąskiej grupie urządzeń o niemalże identycznej mikroarchitekturze. To rozwiązanie mogące sprawdzić się wyłącznie na zamkniętych platformach i to w obliczu niewspółmiernie ogromnego budżetu na produkcję.
Instrukcje maszynowe pozwalają zaoszczędzić zasobów, jednak są kosztowne
Słowo na zakończenie
Uff, dobrnęliśmy do końca. Co zrozumiałe, o samej optymalizacji można by pisać jeszcze dużo, dużo więcej. Rozebrać na czynniki pierwsze kolejne sztuczki graficzne i przytaczać setki przykładów ich praktycznego wykorzystania. Dalej hołdować mistrzów i karcić pozostałych za wpadki. Nie to jest jednak najistotniejsze. Tekst ten stworzyłem, by pośrednio obalić najczęstsze mity, nakierowując na pewien tok rozumowania całego zagadnienia. Oczywiście nie bronię tu ignorancji i partactwa, które wśród deweloperów wyjątkowe bynajmniej nie są, aczkolwiek gorąco zachęcam do dalszej analizy. Bezdyskusyjną prawdą jest, iż w technologii nic nie bierze się znikąd. Każda operacja ma swój koszt, a sprzęt jest zarazem ograniczony. Na pewno warto docenić ludzi, którzy z tym sprzętem robią rzeczy ponad normę, artystycznie zjawiskowe, ale też nie można przy tym zapominać, że za wszystkim bardzo często kryje się drugie, a może nawet trzecie dno ;)
Pokaż / Dodaj komentarze do: Optymalizacja gier, czyli o tym, jak oszukują nas programiści