Wieloplatformowy graficzny interfejs API niskiego poziomu

11

Podczas tworzenia abstrakcji systemu lepiej jest mieć różne interfejsy API ukryte przez wspólny interfejs na najniższym poziomie, który ma sens.

Biorąc pod uwagę różne nowoczesne (bez stałego potoku funkcji) natywne interfejsy API grafiki: OpenGLES 2.0+, OpengGL 3.0+, DirectX 10.0+, Xbox DirectX 9, LibGCM

Jeśli ktoś miałby stworzyć bezstanowy graficzny interfejs API niskiego poziomu, aby usiąść nad nimi wszystkimi, jaki byłby najlepszy sposób, aby uczynić go tak cienkim i najszybszym, jak to możliwe?

NocturnDragon
źródło
Interesujący jest wymóg, aby interfejs API był bezstanowy . Na przykład OpenGL jest stanowy i myślę, że bezstanowy interfejs API, który go otacza, miałby sens tylko wtedy, gdyby był o wiele wyższy poziom, tak że nie trzeba na przykład naciskać i wyrzucać tych samych elementów matematycznych dla każdego powierzchnia, którą renderuje.
SpoonMeiser
Unikanie bezużytecznych zmian stanu można nadal wdrożyć na wyższym poziomie, na przykład sortując wywołania renderowania na podstawie ich stanu przed przesłaniem ich do urządzenia. I ustawiając stan tylko wtedy, gdy różni się od bieżącego.
NocturnDragon
Ale to nie jest bezpaństwowiec. Może się mylę, ale to, co myślę, gdy myślę o bezpaństwowcach, to interfejs API, w którym każde połączenie wcale nie zależy od poprzednich połączeń. Oznacza to, że wszelkie informacje, które normalnie byłyby gdzieś przechowywane, muszą być przekazywane przy każdym połączeniu, które potrzebuje tych informacji. Na przykład w przypadku OpenGL byłyby to matematyki na stosie, oświetlenie, buforowanie Z i opcje normalizacji.
SpoonMeiser
Tak, dla każdego wywołania, którego potrzebujesz, danych siatki, stanu mieszania, tekstur do wiązania, stanów próbkowania itp. Optymalizacje można wykonać później, bez zmiany interfejsu API. A może źle czytam twój komentarz…
NocturnDragon

Odpowiedzi:

6

Najniższy poziom, który ma sens z mojego punktu widzenia, to coś, co mówi o zasobach zaangażowanych w renderowanie - vb / ib, renderowanie powierzchni, tekstur, shaderów, bloków stanów itp.

Problem polega na tym, że niektóre z nich muszą być w różnych formatach, w zależności od interfejsu API - tam jest trochę trudniej. Najłatwiejszym sposobem jest wstępne przetworzenie zasobów statycznych dla odpowiedniego interfejsu API. W przypadku dynamicznych używaj tylko shaderów do ich generowania - dzięki temu pozostawanie w formatach natywnych jest dość proste.

Wszystko, co wtedy robisz na wyższym poziomie, to konfigurowanie potoków z dołączonymi zasobami i przekazywanie ich do GPU. Przekonasz się, że nie wszystko można ładnie wydobyć w ten sposób, zwłaszcza jeśli skorzystasz z trików specyficznych dla sprzętu. Ale to dobry początek.

(Sidenote: jeśli traktujesz sztuczki związane z platformą jako specjalny rodzaj zasobów, możesz posunąć całą tę koncepcję dość daleko).

W ten sposób stworzysz dwie rzeczy: menedżera zasobów sprzętowych oraz zestaw narzędzi do skonfigurowania DAG tych zasobów.

Rachel Blum
źródło
Nigdy nie myślałem o traktowaniu rzeczy związanych z platformą jako zasobów. Brzmi jak bardzo dobry pomysł! Dzięki.
NocturnDragon
10

Biorąc pod uwagę szeroki zakres interfejsów API, które chcesz objąć, typowe podejście do owijania może być nieefektywne i może powodować trudności w mapowaniu koncepcji interfejsów API w kilku innych interfejsach API, które mogą, ale nie muszą, wspierać różne funkcje w różnym stopniu.

W rezultacie najbardziej sensownym podejściem byłoby stworzenie API zorientowanego na funkcje . Chociaż takie podejście uniemożliwia użytkownikowi interfejsu API korzystanie ze wszystkich dostępnych funkcji, znacznie upraszcza implementację każdego zaplecza i umożliwia optymalizacje specyficzne dla zaplecza, które w innym przypadku nie byłyby możliwe.

Znacznie upraszcza także zarządzanie nieobsługiwaną funkcjonalnością dla użytkownika interfejsu API; nie muszą już sprawdzać, czy funkcja X istnieje, i określać, których funkcji dotyczy, ale zamiast tego muszą tylko zapytać samą funkcję, aby sprawdzić, czy jest obsługiwana w bieżącej konfiguracji. Nawet jeśli obsługujesz częściowe lub ograniczone tryby funkcji, podany kontekst znacznie ułatwia zarządzanie.

Jeśli chodzi o tworzenie renderera bezstanowego (zwanego również renderowaniem opartym na przesyłaniu ), zwykle do spakowania i przesłania poleceń do renderowania używa się 64-bitowego klucza . Od tego momentu istnieje duża elastyczność pod względem wykonywania poleceń i informacji, które należy przesyłać, w zależności od funkcji i możliwości, które chcesz obsługiwać.

Jason Kozak
źródło
To właściwie dobry pomysł. I jest to część projektu, który próbuję stworzyć, ale miałem na myśli zaimplementowanie tych funkcji na wspólnym interfejsie API niskiego poziomu. Ale może się zdarzyć, że w przypadku niektórych funkcji nadal będziesz musiał zagłębić się w natywny interfejs API w niektórych bardziej szczególnych przypadkach.
NocturnDragon
Częścią tego pomysłu jest unikanie budowania wspólnego niskiego poziomu API i radzenie sobie z zawijaniem przy użyciu podejścia o najniższym wspólnym mianowniku. Przesuwając poziom abstrakcji o poziom wyżej, nieco ograniczasz zestaw funkcji, ale zyskujesz także możliwość wykorzystania każdej platformy. Aby poradzić sobie z okazjonalną potrzebą głębszego dostępu, wolę zapewnić nagłówek, który ujawnia nagłówki platformy i niektóre wewnętrzne pomocniki; może zepsuć wersję na wersję, ale jest tam, jeśli jej potrzebujesz.
Jason Kozak,
1

Na początek każdy interfejs API działa inaczej, więc nie trzeba dodawać, że owijanie wszystkich powyższych interfejsów API byłoby trudne. To powiedziawszy, czasem trzeba to zrobić: w pewnym momencie gra musi po prostu działać na więcej niż jednej platformie, niezależnie od tego, jak ciężko to zrobić.

Myślę, że najlepszym sposobem na zrobienie tego jest wymyślenie funkcji, które można zaimplementować we wszystkich bazowych interfejsach API, i streszczenie tego i tylko to. Jeśli tworzysz grę wieloplatformową, nie zaimplementowałbyś wszystkich niejasnych funkcji obsługiwanych przez każdy interfejs API, zaimplementowałbyś tylko to, czego potrzebujesz. Pomaga to również utrzymać interfejs API mały i szybki.

Aby uniknąć upakowania implementacji każdego innego interfejsu API w danych wyjściowych, kompilacja powinna odbywać się przy użyciu neutralnych dla platformy plików nagłówkowych i specyficznych dla platformy plików kodu. Wówczas plik kodu specyficzny dla platformy docelowej byłby jedynym skompilowanym, utrzymującym API mały.

Sean James
źródło
0

Jest na ten temat artykuł na temat GPU Pro autorstwa Emila Perssona (Humus)

http://gpupro.blogspot.com/2009/12/making-it-large-beautiful-fast-and.html

Międzyplatformowy interfejs do renderowania. Zalety posiadania takiego oraz sposób, w jaki wcisnęliśmy DX10 we wspólny interfejs z konsolami DX9 i utrzymaliśmy dobrą wydajność.

NocturnDragon
źródło
-4

Możesz sprawdzić bibliotekę SDL lub Allegro . Obie są niskopoziomowymi, wysoce przenośnymi bibliotekami gier, które umożliwiają podłączenie ich w kontekście OpenGL, dzięki czemu można tam renderować swoją grafikę. SDL słynie z tego, że został użyty przez nieistniejącego Loki Games do przeniesienia niektórych popularnych gier z 2000 roku na Linuksa, a Allegro ma dużo czasu i ma świetną społeczność amatorskich twórców gier.

chiguire
źródło
4
To tak naprawdę nie odpowiada na pytanie, nie wspominając o tym, że bardzo możliwe jest zawinięcie zarówno OpenGL, jak i DirectX (patrz Ogre3D, Irrlicht itp.).
Jason Kozak,
Rozważ gry, w które grałeś. Ile z nich ma opcje korzystania z DirectX lub OpenGL? Tak wielu tworzy opakowania dla dwóch bibliotek, aby mogły obsługiwać jedną z nich. Masz ograniczoną wyobraźnię. :-P
Ricket
Rozumiem, że istnieją gry, które pozwalają ci wybrać, czy chcesz renderować grafikę za pomocą OpenGL czy DirectX, ale pytanie dotyczy interfejsu API dla wielu platform, więc myślę, że odpowiedź jest odpowiednia, zredaguję pierwszy akapit, chociaż.
chiguire,
1
pytanie dotyczy międzyplatformowego niskopoziomowego API bezstanowego. SDL i Allegro nie mają z tym nic wspólnego.
NocturnDragon
@NocturnDragon - tytuł pytania jest nieco mylący. Na pierwszy rzut oka spodziewałem się, że pytanie dotyczy wyboru dostępnych interfejsów API i zakładam, że zrobił to również ten odpowiadający.
a_m0d,