Saya sering cenderung melakukan banyak optimalisasi prematur ketika berhadapan dengan grafik. Ada beberapa prinsip yang selalu saya coba ikuti:
- Jaga agar jumlah komponen D3D minimum. (Status render, buffer, shader, dll.)
- Hanya mengikat komponen jika benar-benar diperlukan. (Belum terikat, dll.)
- Spesialisasi komponen sebanyak mungkin. (Hanya mengatur BindFlag yang diperlukan, dll.)
Ini membuat saya membangun pembungkus yang sangat rumit untuk mengelola komponen yang dibuat dan kondisi perpipaan saat ini. Ini tidak hanya menghabiskan banyak waktu pengembangan saya yang berharga, tetapi juga menambah lapisan kompleksitas yang besar.
Dan yang terburuk: saya bahkan tidak tahu apakah itu sepadan dengan masalahnya.
Beberapa pertimbangan optimasi saya mungkin sudah diimplementasikan pada level yang lebih rendah dan saya hanya mereplikasi mereka, juga membuang-buang waktu pada CPU. Pertimbangan lain mungkin sama sekali tidak perlu, karena efek pada kinerja dapat diabaikan.
Jadi pertanyaan saya adalah:
- Manakah dari pedoman di atas yang valid dan sejauh mana saya harus mengikutinya?
- Bagaimana cara GPU menangani perubahan?
- Apa yang terjadi jika saya mengubah keadaan yang tidak pernah digunakan? (Tidak ada panggilan draw yang dilakukan saat sedang aktif.)
- Apa hukuman kinerja aktual untuk mengikat berbagai komponen yang berbeda?
- Pertimbangan kinerja apa yang harus dibuat?
Tolong jangan hanya memberi tahu saya, bahwa saya seharusnya tidak peduli dengan kinerja sampai saya mencapai batas yang sebenarnya. Sementara itu jelas benar dari sudut pandang praktis, saya terutama tertarik pada teori. Entah bagaimana saya perlu melawan keinginan membangun kerangka kerja grafis yang optimal dan saya tidak berpikir saya bisa melakukannya dengan "kuliah optimasi prematur" yang biasa.
Mengelola komponen
Saat ini saya sedang menulis aplikasi DirectX 11 dalam C # menggunakan SlimDX sebagai pembungkus yang dikelola. Ini adalah pembungkus tingkat yang sangat rendah dan abstraksi saya saat ini dibangun di atasnya.
Ada beberapa keuntungan yang jelas ketika menggunakan abstraksi Direct3D. Menyiapkan lingkungan, memuat shader, menyetel konstanta, dan menggambar mesh jauh lebih sederhana dan menggunakan kode yang jauh lebih sedikit. Juga, karena mengelola pembuatan dan pembuangan sebagian besar komponen, mereka dapat secara otomatis digunakan kembali di mana - mana dan saya hampir sepenuhnya menghindari kebocoran memori.
- Bagaimana Anda biasanya mengelola semua komponen grafis dan sumber daya?
- Dapatkah Anda merekomendasikan pembungkus terkelola melakukan sesuatu yang mirip dengan contoh saya di bawah ini?
Ini adalah contoh implementasi saya saat ini. Saya cukup senang dengan antarmuka. Ini memiliki fleksibilitas yang cukup untuk kebutuhan saya dan sangat mudah digunakan dan dipahami:
// 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();
}