Grafik durumunu ve bileşenlerini yönetiyor musunuz?


11

Grafiklerle uğraşırken genellikle çok erken bir optimizasyon yapma eğilimindeyim. Her zaman izlemeye çalıştığım birkaç ilke vardır:

  • D3D bileşenlerinin sayısını minimumda tutun. (Durumları, tamponları, gölgelendiricileri vb. İşle)
  • Bileşenleri yalnızca kesinlikle gerekliyse bağlayın. (Zaten bağlı değil vb.)
  • Bileşenleri mümkün olduğunca uzmanlaştırın. (Yalnızca gerekli BindFlags vb. Ayarlayın)

Bu, beni oluşturulan bileşenleri ve mevcut borulama durumunu yönetmek için çok ayrıntılı sarmalayıcılar oluşturmaya götürdü. Bu sadece değerli gelişim zamanımın çoğunu tüketmekle kalmaz, aynı zamanda başka bir büyük karmaşıklık katmanı ekler.

Ve en kötüsü: Her şeyin belaya değip değmeyeceğini bile bilmiyorum.

Optimizasyonla ilgili düşüncelerimin bazıları zaten daha düşük bir düzeyde uygulanabiliyor ve bunları tekrar ediyorum, ayrıca CPU'da zaman harcıyorum. Performans üzerindeki etkisi önemsiz olduğu için diğer hususlar tamamen gereksiz olabilir.

Yani sorularım:

  1. Yukarıdaki kılavuzlardan hangisi geçerlidir ve ne ölçüde uymalıyım?
  2. GPU durum değişikliklerini nasıl gerçekleştirir?
  3. Hiç kullanılmayan bir durumu değiştirirsem ne olur? (Etkinken hiçbir çizim çağrısı yapılmaz.)
  4. Çeşitli bileşenleri birleştirmek için gerçek performans cezaları nelerdir?
  5. Başka hangi performans hususları dikkate alınmalıdır?

Lütfen bana sadece gerçek sınırlara ulaşana kadar performansı önemsememem gerektiğini söylemeyin. Bu pratik açıdan açık olsa da, esasen teoriyle ilgileniyorum. Bir şekilde optimal grafik çerçevesini oluşturma dürtüsü ile mücadele etmem gerekiyor ve bunu "erken optimizasyon dersi" ile yapabileceğimi sanmıyorum.

Bileşenleri yönetme

Şu anda yönetilen sarıcı olarak SlimDX kullanarak C # DirectX 11 uygulamaları yazıyorum. Çok düşük seviyeli bir sargıdır ve mevcut soyutlamam bunun üzerine inşa edilmiştir.

Direct3D soyutlama kullanmanın bazı belirgin avantajları vardır. Ortamı kurmak, gölgelendiricileri yüklemek, sabitleri ayarlamak ve bir kafes çizmek çok daha basittir ve çok daha az kod kullanır . Ayrıca, çoğu bileşenin oluşturulmasını ve atılmasını yönettiği için, otomatik olarak her yerde yeniden kullanılabilirler ve bellek sızıntılarından neredeyse tamamen kaçınırım.

  1. Tüm grafik bileşenlerini ve kaynaklarını genellikle nasıl yönetirsiniz?
  2. Aşağıdaki örneğime benzer bir şey yapmayı yöneten herhangi bir sarmalayıcı önerebilir misiniz?

İşte mevcut uygulamamın bir örneği. Arayüzden oldukça memnunum. İhtiyacım için yeterli esnekliğe sahip ve kullanımı ve anlaşılması çok basit:

// Init D3D environment
var window = new RenderForm();
var d3d = new Direct3D(window, GraphicsSettings.Default);
var graphics = new GraphicsManager(d3d.Device);

// Load assets
var mesh = GeometryPackage.FromFile(d3d, "teapot.gp");
var texture = Texture.FromFile(d3d, "bricks.dds");

// Render states
graphics.SetViewports(new Viewport(0, 0, 800, 600);
graphics.SetRasterizer(wireFrame: false, culling: CullMode.Back);
graphics.SetDepthState(depthEnabled: true, depthWriteEnabled: true);
graphics.SetBlendState(BlendMethod.Transparency);

// Input layout
graphics.SetLayout("effect.fx", "VS", "vs_4_0",
    new InputElement("POSITION", 0, Format.R32G32B32_Float, 0),
    new InputElement("TEXCOORD", 0, Format.R32G32_Float, 0)
);

// Vertex shader
graphics.SetShader(Shader.Vertex, "effect.fx", "VS", "vs_4_0");
graphics.SetConstants(Shader.Vertex, 0, 4, stream => stream.Write(wvpMatrix));

// Pixel shader
graphics.SetShader(Shader.Pixel, "effect.fx", "PS", "ps_4_0");
graphics.SetTexture(Shader.Pixel, 0, texture);
graphics.SetSampler(Shader.Pixel, 0, Sampler.AnisotropicWrap);
graphics.SetConstants(Shader.Pixel, 0, 1, stream => stream.Write(new Color4(1, 0, 1, 0);

d3d.Run(() =>
{
    // Draw and present
    d3d.BackBuffer.Clear(new Color4(1, 0, 0.5f, 1));
    graphics.SetOutput(d3d.BackBuffer);
    graphics.Draw(mesh);
    d3d.Present();
}

8
Bu tür bir soru için "erken optimizasyon" dersini vermeyeceğim, size "profil değişikliklerini kendiniz görebilmeniz" dersini verirdim.
Tetrad

@ Tetrad Bunun oldukça iyi bir tavsiye olduğunu kabul etmekten neredeyse utanıyorum. Kesinlikle daha fazla profilleme yapmalıyım.
Lucius

1
Profil sayıları "resimler ya da olmadı" oyunlarının gamedev versiyonudur =)
Patrick Hughes

Yanıtlar:


3

Gamedev.net'te bu konularda Hodgman tarafından özetlenen soyutlama yaklaşımını seviyorum:

Üç katmanlı bir oluşturma sistemini tanımlar:

  1. Direct3D 9, Direct3D 11 ve OpenGL gibi farklı grafik API'leri arasındaki farkları aşmayan, "komutları" kabul eden düşük düzeyli oluşturma API'sı. Her "komut", bir tepe akışını veya dokusunu bağlama veya ilkelleri çizme gibi farklı bir durum veya çizim çağrısıyla eşleşir.
  2. Tüm durumları ve belirli bir nesneyi oluşturmak için gereken tek bir çizim çağrısını bir araya getiren "oluşturma öğeleri" ni kabul eden ve bunları ilk düzeye gönderilen komutlara dönüştüren ve dönüştüren API. Oluşturma durumu, durum değişikliklerini mantıksal olarak gruplandıran bir çizim çağrısı ve bir "durum grupları" yığını içerir. Örneğin, render geçişi için bir durum grubunuz, malzeme için bir durum grubunuz, geometri için bir durum grubunuz, örnek için bir durum grubunuz vb. Bu seviye, gereksiz durum değişikliklerini azaltmak için bu render öğelerini sıralamaktan ve aslında gereksiz olan herhangi bir durum değişikliğini kaldırmaktan sorumludur.
  3. Sahne öğelerini ikinci düzeye gönderen bir sahne grafiği veya GUI oluşturucu gibi üst düzey sistemler. Dikkat edilmesi gereken önemli olan, bu sistemlerin durum sıralama algoritmaları veya belirli oluşturma API'sı hakkında bilgi sahibi olmamasıdır ve bu da onları tamamen platformdan bağımsız kılar. Ayrıca, alt düzey API'ler uygulandıktan sonra kullanımı kolaydır.

Sonuç olarak, bu model her iki probleminizi de aynı anda çözer.

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.