Grafik kaynaklarını eşzamansız olarak nasıl yüklerim?


9

Platformdan bağımsız düşünelim: Oyunun geri kalanı devam ederken bazı grafik kaynakları yüklemek istiyorum.

Prensip olarak, gerçek dosyaları ayrı bir iş parçacığına veya zaman uyumsuz G / Ç kullanarak yükleyebilirim. Ancak grafik nesnelerle, bunları GPU'ya yüklemem gerekecek ve bu (genellikle) yalnızca ana iş parçacığında yapılabilir.

Oyun döngümü böyle bir şeye benzeyecek şekilde değiştirebilirim:

while true do
    update()
    for each pending resource do
        load resource to gpu
    end
    draw()
end

diskten RAM'e ayrı bir iş parçacığı yük kaynakları var.

Ancak, yüklenecek birçok büyük kaynak varsa, bu bir çerçeve son tarihini kaçırmama ve sonunda bırakılan çerçevelere ulaşmama neden olabilir. Bu yüzden döngüyü buna değiştirebilirim:

while true do
    update()
    if there are pending resources then
        load one resource to gpu
        remove that resource from the pending list
    end
    draw()
end

Her çerçeve için yalnızca tek bir kaynağı etkili bir şekilde yükleme. Ancak, yüklenecek çok sayıda küçük kaynak varsa, bunların tümünü yüklemek çok sayıda çerçeve alacak ve çok fazla zaman harcanacaktır.

Optimal olarak, yüklememi aşağıdaki şekilde zamanlamak istiyorum:

while true do
    time_start = get_time()
    update()
    while there are pending resources then
        current_time = get_time()
        if (current_time - time_start) + time_to_load(resource) >= 1/60 then
            break
        load one resource to gpu
        remove that resource from the pending list
    end
    draw()
end

Bu şekilde, yalnızca bu çerçeve için sahip olduğum süre içinde yapabilirsem bir kaynak yüklerdim. Ne yazık ki, bu belirli bir kaynağı yüklemek için gereken süreyi tahmin etmenin bir yolunu gerektirir ve bildiğim kadarıyla, bunu yapmanın genellikle bir yolu yoktur.

Burada ne eksik? Birçok oyun, tüm eşyalarını tamamen eşzamansız olarak ve atlanan kareler veya aşırı uzun yükleme süreleri olmadan nasıl yükleyebilir?

Yanıtlar:


7

Mükemmel bir dünya olduğunu varsayarak başlayalım. Bir kaynağı yüklemek için iki adım vardır: önce onu depolama ortamınızdan çıkarır ve doğru formatta belleğe alırsınız ve ikincisi onu bellek veriyolundan video belleğine aktarırsınız. Bu iki adımdan hiçbirinin ana iş parçanızda zaman kullanması gerekmez; yalnızca bir G / Ç komutu vermek için dahil edilmesi gerekir. Kaynak kopyalanırken hem CPU'nuz hem de GPU'nuz başka şeyler yapmaya devam edebilir. Tüketilen tek gerçek kaynak bellek bant genişliği.

Siz ve donanım arasında soyutlama katmanı olmayan bir platform kullanıyorsanız, API bu kavramları doğrudan doğrudan ortaya koyar. Ancak bir PC'deyseniz, muhtemelen sizinle GPU arasında oturan bir sürücü var ve işleri bir şekilde yapmak istiyor. API bağlı olarak olabilir sürücü sahip olduğunu bazı belleğe doku kopyalar "doku oluşturmak" API çağrısı daha muhtemel sahibi olduğu hafıza ile destek vermekle birlikte bir doku oluşturmak mümkün. Bu durumda, bir doku oluşturmak, sabit bir ek yüke ve bir miktar dokunun boyutuyla orantılı olacaktır. Bundan sonra sürücü herhangi bir şey yapabilir - dokuyu proaktif olarak VRAM'a aktarabilir veya ilk kez kullanmaya çalışana kadar dokuyu yüklemeyi rahatsız etmeyebilir.

Sen ya da bu konuda bir şeyler yapmaya muktedir olmayabilir, ancak olabilir o "doku oluşturmak" çağrısı yapmak için gereken süreyi bir guesstimate olun. Tabii ki, tüm sayılar donanıma ve yazılıma bağlı olarak değişecektir, bu yüzden muhtemelen tersine mühendislik yapmak için bir sürü zaman harcamaya değmez. Sadece deneyin ve görün! Bir metrik seçin: "kare başına doku sayısı" veya "kare başına toplam doku boyutu", bir kota seçin (örneğin, kare başına 4 doku) ve stres testine başlayın.

Patolojik durumlarda, her iki kotayı da aynı anda izlemeniz gerekebilir (örneğin, çerçeve başına 4 doku veya çerçeve başına 2 MB doku, hangisi daha düşükse sınırla). Ancak çoğu doku akışının asıl püf noktası, hangi dokuları sınırlı belleğinize sığdırmak istediğinizi bulmaktır , onları kopyalamak için ne kadar zaman harcadığınızı değil.

Ayrıca, doku oluşturma için patolojik vakalar - aynı anda ihtiyaç duyulan çok sayıda küçük doku gibi - diğer alanlar için de patolojik vakalar olma eğilimindedir. Bir dokunun kopyalanması gereken mikrosaniyeyi tam olarak düşünmeden önce basit bir çalışma uygulaması elde etmeye değer. (Artı, gerçek performans isabeti "doku oluştur" çağrısında CPU zamanı olarak değil, dokuyu kullandığınız ilk karede GPU zamanı olarak gerçekleşebilir.)


Bu oldukça iyi bir açıklama. Bir sürü şey bilmiyordum ama çok mantıklı. Stres testi yapmak yerine, çalışma zamanında doku oluşturma yükünü ölçürüm, yavaşça başlarım ve mevcut yürütme süresinin% 80'ini aykırı değerlere yer bırakmak için söyleyeceğim.
Panda Pijama

@PandaPajama Bundan biraz şüpheliyim. Kararlı durumun "hiçbir kopya kopyalanmadı" ve büyük miktarda varyans olmasını beklerdim. Dediğim gibi, isabetin bir kısmının, dokuyu kullanan ilk render çerçevesi olduğundan şüpheleniyorum, bu da performansı etkilemeden dinamik olarak ölçülmesi çok daha zor.
John Calsbeek

Ayrıca, asenkron doku transferleri hakkında bir NVIDIA sunumu. Okuduğum kadarıyla eve doğru gitmesinin en önemli yanı, yükledikten hemen sonra bir doku kullanmanın durmasıdır. developer.download.nvidia.com/GTC/PDF/GTC2012/PresentationPDF/…
John Calsbeek

Ben bir sürücü geliştirici değilim, ama bu yaygın mı? Sürücüleri bu şekilde uygulamak çok mantıklı değil, çünkü doku ilk kullanımlarının zaman çizelgesi boyunca aralıklı olmak yerine ani artışlar (her seviyenin başında olduğu gibi) olması muhtemeldir.
Panda Pijama

@PandaPajama Uygulamalarda, mevcut VRAM'dan daha fazla doku oluşturmak, doku oluşturmak ve daha sonra bunları asla kullanmak yaygın değildir. Yaygın bir durum "bir grup doku oluşturmak ve sonra hemen bunları kullanan bir sahne çizmek" dir, bu durumda tembel olmak sürücüye yardımcı olur, çünkü hangi dokuların gerçekten kullanıldığını anlayabilir ve ilk çerçeve yine de otostop çekecektir . Ama ben bir sürücü geliştiricisi de değilim, bir tuz tanesi ile al (ve test et!).
John Calsbeek
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.