Homebrew oluşturma sistemimdeki kaynakları önbelleğe alma


10

Arka fon:

C ++ ve OpenGL kullanarak varlık bileşeni sistem türü mimarisi için basit bir 3D render sistemi tasarlıyorum. Sistem bir oluşturucu ve bir sahne grafiğinden oluşur. Oluşturucunun ilk yinelemesini tamamladığımda, sahne grafiğini ECS mimarisine dağıtabilirim. Şimdilik bu bir şekilde yer tutucudur. Mümkünse, oluşturucu için hedeflerim şunlardır:

  1. Sadelik . Bu bir araştırma projesi için ve sistemlerimi kolayca değiştirip genişletmek istiyorum (dolayısıyla ECS yaklaşımı).
  2. Performans . Sahnemin birçok küçük modeli ve ayrıca çok fazla geometriye sahip büyük hacimleri olabilir. Her render karesinde OGL bağlamından ve arabellek geometrisinden nesne almak kabul edilemez. Önbellek hatalarını önlemek için veri yerelliğini hedefliyorum.
  3. Esneklik . Sprite, model ve cilt (voksel) oluşturabilmelidir.
  4. Ayrılmış . Oluşturucumu yazdıktan sonra sahne grafiği çekirdek ECS mimarisine yeniden yansıtılabilir.
  5. Modüler . Sahne grafiğimi değiştirmeden farklı oluşturucularda takas edebilmek güzel olurdu.
  6. Referans şeffaflığı , yani herhangi bir zamanda ona herhangi bir geçerli sahne verebilirim ve o sahne için her zaman aynı görüntüyü oluşturur. Özellikle bu hedefe gerek yoktur. Sahne serileştirmeyi basitleştirmeye yardımcı olacağını düşündüm (sahneleri kaydedip yükleyebilmem gerekecek) ve test / deneme amaçlı çalışma sırasında farklı sahnelerde takas etmem için esneklik verdim.

Sorun ve fikirler:

Denemek için bazı farklı yaklaşımlar ile geldim ama her render düğüm için OGL kaynakları (VAO, VBOs, gölgelendiriciler, vb) nasıl önbellek ile mücadele ediyorum. Şimdiye kadar düşündüğüm farklı önbellekleme kavramları şunlardır:

  1. Merkezi önbellek. Her sahne düğümü bir kimliğe ve oluşturucuda düğümleri oluşturmak için kimlikleri eşleyen bir önbellek bulunur. Her oluşturma düğümü, geometriyle ilişkili VAO ve VBO'ları içerir. Önbellek kaçışı kaynakları alır ve geometriyi önbellekteki bir oluşturma düğümüyle eşler. Geometri değiştirildiğinde kirli bir bayrak ayarlanır. Oluşturucu sahne düğümleri boyunca yineleme yaparken kirli bir geometri bayrağı görürse, oluşturma düğümünü kullanarak verileri yeniden engeller. Bir sahne düğümü kaldırıldığında, bir olay yayınlanır ve oluşturucu kaynakları serbest bırakırken ilişkili oluşturma düğümünü önbellekten kaldırır. Alternatif olarak, düğüm çıkarılmak üzere işaretlenir ve oluşturucu onu kaldırmaktan sorumludur. Bence bu yaklaşım 4 ve 5'i de göz önünde bulundurarak hedef 6'ya en yakın şekilde ulaşır.
  2. Dağıtılmış önbellek . Yukarıdaki her sahne düğümü dışında benzer bir oluşturma düğümü vardır. Bu harita aramasını atlar. Veri yerini belirlemek için, oluşturma düğümleri oluşturucuda saklanabilir. Daha sonra sahne düğümlerinin düğümleri işlemek için işaretçileri olabilir ve oluşturucu işaretçiyi bir önbellek özlemine ayarlar. Bence bu tür bir varlık bileşeni yaklaşımını taklit eder, bu yüzden mimarinin geri kalanıyla tutarlı olacaktır. Buradaki sorun, şimdi sahne düğümlerinin oluşturucu uygulamasına özgü verileri tutmasıdır. İşleyicilerin işleniş biçimini değiştirirsem (spriteları ciltlere dönüştürmek gibi) şimdi render düğümünü değiştirmem veya sahne düğümüne daha fazla "bileşen" eklemem gerekiyor (bu da sahne grafiğini değiştirmek anlamına geliyor). Artı tarafta, bu ilk iterasyon oluşturucumu çalıştırıp çalıştırmanın en basit yolu gibi görünüyor.
  3. Dağıtılmış meta veriler . Oluşturucu önbellek meta veri bileşeni her sahne düğümünde depolanır. Bu veriler uygulamaya özgü değildir, bunun yerine önbellek için gerekli olan bir kimlik, tür ve diğer ilgili verileri içerir. Daha sonra önbellek araması, ID kullanılarak doğrudan bir dizide yapılabilir ve tür, hangi oluşturma yaklaşımının kullanılacağını (sprite'lar ve birimler gibi) gösterebilir.
  4. Ziyaretçi + dağıtılmış haritalama . Oluşturucu bir ziyaretçidir ve sahne düğümleri ziyaretçi düzenindeki öğelerdir. Her sahne düğümü, yalnızca oluşturucunun işlediği bir önbellek anahtarını (meta veriler gibi, yalnızca bir kimlik gibi) tutar. Kimlik, genelleştirilmiş harita araması yerine dizi için kullanılabilir. Oluşturucu, sahne düğümünün, sahne düğümünün türüne göre farklı bir oluşturma işlevi göndermesine izin verebilir ve kimlik, herhangi bir önbellek tarafından kullanılabilir. Varsayılan veya aralık dışı bir kimlik önbellek kaybını gösterir.

Bu sorunu nasıl çözersiniz? Veya öneriniz var mı? Metin duvarımı okuduğunuz için teşekkürler!


1
Herhangi bir ilerleme kaydettiniz mi?
Andreas

Bu son derece karmaşık bir sorudur ve muhtemelen birkaç ayrı soruya bölünmelidir. Bu aslında "Motorumu nasıl tasarlamalıyım?" Benim tavsiyem, önce daha basit bileşenleri destekleyen bir şey tasarlamak, daha sonra özellikleri ekleyip yeniden düzenlemek olacaktır. Ayrıca, aradığınız bilgilerin çoğunu içermesi gereken 3D oyun motoru tasarım kitaplarına bakın.
Ian Young

Yanıtlar:


2

Sorunuzu tekrar okuduktan sonra, sorunu aşırı derecede karmaşık hale getirdiğinizi hissediyorum. İşte nedeni:

  1. Gerçekten iki tür oluşturma sistemi vardır: İleri ve Ertelenmiş, hiçbiri sahne grafiğine bağlı değildir.

  2. Herhangi bir oluşturma sistemi ile gerçekten almanız gereken tek performans sorunu, yüksek poli sayımı ve verimsiz gölgelendirici ve istemci kodundan gelmelidir.

  3. Önbellek özledikleri gerçekten performansı düşürür, ancak olduklarını düşündüğünüz canavarlar değildir. Performans iyileştirmelerinizin% 80'i daha verimli bir algoritmadan olacaktır. Kodunuzu önceden optimize etme hatasını yapmayın.

Bahsedilen:

Bir homebrew sahne grafiği kullanıyorsanız, sahne grafiği kodunuzun oluşturma bölümünü tasarlamak için zaten bir "Oluşturucu" arabirimi (veya temel sınıf) kullanıyor olmanız gerekir. Çift gönderim kullanan ziyaretçi kalıbı, renk, doku, kafes, dönüşüm vb. önce sahne ağacı yapısını derinlemesine yürü, kendini argüman olarak geçir. Bu şekilde oluşturucu temel olarak sadece gölgelendiricilerden oluşan bir koleksiyon ve belki de bir ya da iki çerçeve tamponudur. Bunun sonucu, arama / kaldırma kodunun artık oluşturma sistemi için gerekli olmadığı, yalnızca sahne grafiğinin kendisidir.

Karşılaştığınız sorunların üstesinden gelmenin kesinlikle başka yolları da var, ama çok uzun soluklu bir cevap vermek istemiyorum. Bu nedenle, en iyi tavsiyem önce basit bir şey çalışmak, sonra zayıflıklarını bulmak için genişletin, daha sonra diğer yaklaşımlarla denemeler yapın ve güçlü / zayıf yönlerinin pratikte nerede olduğunu görün.

Sonra bilinçli bir karar vermek için iyi yerleştirilmiş olacak.

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.