Oyun döngüsü ve openGL arasında çoklu kullanımdan yararlanma


10

OpenGL oluşturucusuna dayalı bir oyun bağlamında konuşma:

İki iş parçacığı olduğunu varsayalım:

  1. Oyun içi nesneler için oyun mantığı ve fizik vb.

  2. Oyun nesnelerindeki verilere dayanarak her oyun nesnesi için openGL çizim çağrıları yapar (1 numaralı konu güncellenmeye devam eder)

Oyunun şu anki durumunda her oyun nesnesinin iki kopyası yoksa, Konu 2'yi duraklatmanız gerekirken, Konu 2 çizim çağrısı yapar, aksi takdirde oyun nesneleri söz konusu nesne için bir çizim çağrısının ortasında güncellenir. istenmeyen bir durumdur!

Ancak, iplik 2'den güvenli bir şekilde telefon görüşmesi yapmak için iplik 1'i durdurmak, çoklu kullanım / eşzamanlılığın tüm amacını öldürür

Bunun için yüzlerce veya binlerce kullanmak veya nesneleri / çitleri senkronize etmekten daha iyi bir yaklaşım var mı, böylece çok çekirdekli mimari performans için kullanılabilir mi?

Hala mevcut oyun durumunun bir parçası olan nesneler için doku yüklemek ve gölgelendiricileri derlemek için multithreading kullanabileceğimi biliyorum, ancak çizim ve güncelleme ile çakışmaya neden olmadan aktif / görünür nesneler için nasıl yapabilirim?

Oyun nesnesinin her birinde ayrı senkronizasyon kilidi kullanırsam ne olur? Bu şekilde, herhangi bir iş parçacığı tüm güncelleme / çizim döngüsü yerine yalnızca bir nesne üzerinde (ideal durum) engellenir! Ancak her bir nesneye kilit almak ne kadar maliyetli (oyunun bin nesnesi olabilir)?


1. Sadece iki diş olacağı varsayılarak iyi ölçeklenmez, 4 çekirdek çok yaygındır ve sadece artacaktır. 2. En iyi uygulama stratejisi yanıtı: Komut Sorgusu Sorumluluk Ayrımı ve Aktör Modeli / Bileşen Varlık Sistemi'ni uygulayın. 3. Gerçekçi cevap: sadece kilitler ve malzeme ile geleneksel C ++ yolu kesmek.
Den

Bir ortak veri deposu, bir kilit.
Justin

@justin tıpkı bir senkronizasyon kilidi ile söylediğim gibi, çoklu iş parçacığının tek avantajı gün ışığında vahşice öldürülecek, güncelleme iş parçacığı tüm nesneler için çağrı yapana kadar beklemek zorunda kalacak, ardından çizim iş parçacığı güncelleme öğelerini güncelleme tamamlayana kadar çekme iş parçacığı bekleyecek ! bu tek dişli yaklaşımdan daha kötü
Allahjane

1
Async grafik api (örn. OpenGL) içeren oyunlarda çok iş parçacıklı yaklaşım hala aktif bir konu ve bu standart veya mükemmel bir çözüm yok gibi görünüyor
Allahjane

1
Motorunuz ve oluşturucunuz için ortak olan veri deposu oyun nesneleriniz olmamalıdır. Oluşturucunun mümkün olduğunca çabuk işleyebileceği bir temsil olmalıdır.
Justin

Yanıtlar:


13

Kilitleri kullanarak tanımladığınız yaklaşım çok verimsiz ve büyük olasılıkla tek bir iş parçacığı kullanmaktan daha yavaş olacaktır. Her bir evre içinde veri kopyalarını tutmak için diğer yaklaşım muhtemelen "hızlı-akıllı", ancak kopyaları senkronize tutmak için engelleyici bir bellek maliyeti ve kod karmaşıklığı ile iyi çalışır.

Buna birkaç alternatif yaklaşım var, çok iş parçacıklı oluşturma için popüler bir çözüm, çift tamponlu komutlar kullanmaktır. Bu, oluşturucu arka ucunun, tüm çizim çağrılarının ve oluşturma API'sı ile iletişimin gerçekleştirildiği ayrı bir iş parçacığında çalıştırılmasını içerir. Oyun mantığını çalıştıran ön uç iş parçacığı, bir komut arabelleği (çift arabelleğe alınmış) aracılığıyla arka uç oluşturucu ile iletişim kurar. Bu kurulumla, bir kareyi tamamlarken yalnızca bir senkronizasyon noktanız olur. Ön uç bir arabelleği oluşturma komutlarıyla doldururken, arka uç diğerini tüketiyor. Her iki iplik de dengeli ise, hiçbiri açlıktan ölmemelidir. Ancak bu yaklaşım, oluşturulan karelerde gecikme getirdiğinden, OpenGL sürücüsünün bunu zaten kendi işleminde yapması muhtemel olduğundan performans kazançlarının dikkatlice ölçülmesi gerekecektir. Ayrıca en iyi ihtimalle sadece iki çekirdek kullanır. Bu yaklaşım Doom 3 ve Quake 3 gibi birkaç başarılı oyunda kullanılmıştır.

Çok çekirdekli CPU'ları daha iyi kullanan daha ölçeklenebilir yaklaşımlar, ikincil bir iş parçacığında hizmet verilen eşzamansız bir isteği tetiklerken bağımsız görevlere dayanan, isteği tetikleyen iş parçacığı başka bir işle devam eden yaklaşımlardır. Görev, kilitleri önlemek için diğer dişlerle hiçbir bağımlılığa sahip olmamalıdır (ayrıca veba gibi paylaşılan / global verilerden kaçının!). Görev tabanlı mimariler, oyun animasyonları, AI yol bulma, prosedür oluşturma, sahne sahne dinamiklerinin yüklenmesi vb. Gibi oyunun yerelleştirilmiş bölümlerinde daha kullanılabilir. Oyunlar doğal olarak etkinlikle dolu, çoğu etkinlik zaman uyumsuz, bu yüzden bunları ayrı iş parçacıklarında çalıştırmak kolaydır.

Son olarak, okumanızı tavsiye ederim:


sadece merak! Doom 3'ün bu yaklaşımı nasıl kullandığını biliyor musunuz? Geliştiricilerin tekniklere asla izin vermediğini düşündüm!
15:12

4
@Allahjane, Doom 3 Açık Kaynak . Sağladığım bağlantıda, oyunun genel mimarisinin bir incelemesini bulacaksınız. Ve yanılıyorsunuz, evet tamamen Açık Kaynak oyunları bulmak nadirdir, ancak geliştiriciler genellikle tekniklerini ve püf noktalarını bloglar, makaleler ve GDC gibi etkinliklerde ortaya çıkarır .
Glampert

1
Hmm. Bu harika bir okuma oldu! beni bunun hakkında bilgilendirdiğin için teşekkürler! Sen kene olsun :)
Allahjane
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.