Język i biblioteki

11123530043_1d28f2fa35_o

W tym krótkim poście opiszę jakich technologii korzystam przy Avocado i co zmotywowało mnie do ich użycia.

Język

Zdecydowałem się na użycie C++ z kilku powodów:

  1. Jest to język z którym mam najwięcej doświadczenia i wydaje mi się że pozwoli mi to na najszybszą zmianę pomysłu w działający kod. Myślałem nad wyborem jednej z nowszych alternatyw, m. in. Go albo Rust, ale obawiałem się że więcej czasu spędziłbym nad szukaniem rozwiązań do problemów, które w C++ są dla mnie oczywiste i spotkałem się z nimi przy poprzednich projektach (AnotherNES) niż nad pisaniem właściwego kodu.
  2. Duża ilość bibliotek - nie muszę martwić się o to, że biblioteka do obsługi danej funkcjonalności nie jest przeportowana lub zawiera błędy uniemożliwiające mi pracę nad projektem. W przypadku gdy nie będę chciał wynajdować koła od nowa mogę sięgnąć po gotowe rouzwiązanie.
  3. Wieloplatformowość - ten sam kod po niewielkich zmianach mogę skompilować na Linuksie, OS X, Androidzie, Raspberry Pi czy nawet do JavaScriptu (co pokazałem na moim poprzednim projekcie). C/C++ to chyba jedyne języki które mogę uruchomić na dowolnej architekturze nie tracąc na wydajności.
  4. Natywność - emulacja to taka dziedzina gdzie niskopoziomowość przy zarządzaniu pamięcią i procesorem jest koniecznością, a mechanizmy takie jak GC czy brak dostępu do surowej pamięci działa wyłącznie na naszą niekorzyść - dlatego odrzuciłem języki interpretowane i kompilowane w locie. Zostaje więc jedynie C, C++ i nowy Rust.
  5. Narzędzia - Visual Studio to jedno z najlepszych środowisk jakie miałem przyjemność używać (do póki nie poznałem środowisk firmy JetBrains). Szczególnie dopracowanym jest narzędziem jest tutaj debugger, z którym spędzam dużo czasu i bardzo usprawnia pracę. Poza światem Windowsa mamy LLVM + szereg narzędzi służących do analizy statycznej kodu, automatycznego formatowania składni czy badania programu pod kątem wycieków pamięci i innych popularnych błędów.

Biblioteki

SDL2 - używałem jej wiele razy, znam jej wady i zalety. Wersja 2.0 przyniosła wiele usprawnień jak obsługa wielu okien, sprzętowe renderowanie obrazu, unifikacja kontrolerów do gier (zmapowanie dowolnego kontrolera na schemat padu Xbox 360 który stał się swego rodzaju standardem na PC) i bezproblemowa obsługa OpenGL w nowszych wersjach. Najważniejszym argumentem który spowodował to że wybrałem ją zamiast SFML lub innej biblioteki jest (podobnie jak w przypadku C++) wieloplatformowość.

OpenGL 3.2 - specyfikacja w tej wersji zrywa kompatybilność wsteczną z tzw. fixed pipeline na rzecz shaderów. W poprzednich wersjach takie rzeczy jak światło, cienie czy tekstury były ustawiane z kodu, ale obecne karty graficzne (a konkretnie ich sterowniki) symulują te funkcjonalności w sprytnie zaszytych shaderach. Shadery dają ogromne możliwości przy tworzeniu grafiki komputerowej co może się przydać gdy będę chciał usprawniać grafikę generowaną przez konsolę. Dodatkowo wersja 3.2 jest bardzo zbliżona do OpenGl ES 2.0, który dominuje na urządzeniach niebędącymi komputerami osobistymi co znowu usprawnia proces portowania na inne platformy. Z Direct3D zrezygnowałem z powodu ograniczenia do jednej platformy.

Ciekawą technologią jest Vulkan, ale on dopiero raczkuje i jego celem nie jest zastąpienie OpenGl, a wypełnienie luki tam gdzie inne biblioteki powodują zbyt duży narzut wydajnościowy.

ImGUI - prosta biblioteka do tworzenia GUI posiadająca spore możliwości. Bardzo łatwo integruje się z bibliotekami 3d, jest szybka i banalna w użyciu. Jej implementacja zajmuje się całym boilerplate, my tylko definiujemy w locie jakie widgety chcemy wyświetlić i jak mamy zareagować na eventy. Pozwala na szybkie prototypowanie i tworzenie bardziej skomplikowanych narzędzi jak edytor pamięci, debugger i inne. W związku z tym, że generuje obraz w formie przyjaznej bibliotekom 3d nie ogranicza ją dana platforma.

Przy zgłaszaniu projektu na Daj się poznać wspomniałem też o HTML, CSS i JS. Potraktowałem to jako eksperyment, gdzie chciałbym powyższe technologie użyć jako zaawansowany interfejs do debugowania i manipulacji emulatorem. Serwerem byłby sam emulator który udostępniałby dane w czasie rzeczywistym z użyciem WebSocketów. Możliwości są duże - przykładowo wizualizacja aktualnie przesyłanych danych do GPU jak tekstury, modele i renderowanie ich z użyciem three.js.

 

Zapraszam do śledzenia na Twitterze oraz do komentowania.

Ten wpis został opublikowany w kategorii Avocado i oznaczony tagami , . Dodaj zakładkę do bezpośredniego odnośnika.
  • C++ i wieloplatformowość? Prawdę mówiąc chyba prawie nie znam mniej wieloplatformowych języków niż ten…

    • Jakub Czekański

      Mówiąc wieloplatformowość mam na myśli obsługę wielu platform zarówno pod względem systemów jak i architektur.

      Pisząc w języku typu "write once, run anywhere" (przykładowo Java lub Python) raz napisany kod będę mógł uruchomić zarówno na Windowsie jak i na Linuksie bez żadnych zmian używając tych samych plików. To ogromna zaleta i takie coś nie jest możliwe w C, bo program na każdą platformę trzeba przystosować i skompilować oddzielnie.

      Jednakże to czy program mogę uruchomić na danej platformie zależy od tego, czy maszyna wirtualna lub interpreter został na nią przeportowany – przykładowo pisząc w Pythonie mogę zapomnieć o platformach mobilnych, podobnie w przypadku Javy (czy .net, ale to powoli się zmienia).

      Istnieją bardziej egzotyczne platformy które chcę spróbować. Jedyne wymaganie to działający kompilator c++, a on jest dostępny na prawie każdej platformie. Przykładowo gdybym chciał uruchomić program na konsoli 3ds czy jakiejś płytce z procesorem ARM nic nie stoi na przeszkodzie.

      Zapomniałem w poście wspomnieć o jeszcze jednej rzeczy – natywny język pozwala na dynamiczne generowanie kodu. Jest to wymagane przy implementacji JITa.

    • Sebastian Gierłowski

      Wydaje mi się że w przypadku c++ bardziej odpowiednie będzie słowo przenośny niż wieloplatformowy, co nie oznacza że nie można tego określenia podciągnąć pod c++. Wieloplanowość języka programowania to z definicji przecież jego zdolność do działania aplikacji w nim skompilowanych na wielu platformach przy napisaniu kodu tylko raz. Zakładając że w programie nie zostaną użyte biblioteki specyficzne dla danej platformy c++ taką możliwość udostępnia. Trzeba też pamiętać że nawet w językach opartych na maszynie wirtualnej często zachodzi potrzeba rekompilacji programu dla innych platform.