ฉันมักจะทำ optimazation ก่อนกำหนดจำนวนมากเมื่อต้องรับมือกับกราฟิก มีหลักการบางอย่างที่ฉันพยายามทำตามอยู่เสมอ:
- รักษาจำนวนองค์ประกอบ D3D ให้น้อยที่สุด (สถานะการแสดงผลบัฟเฟอร์ตัวติดตั้ง ฯลฯ )
- ผูกส่วนประกอบถ้าจำเป็นจริงๆ (ไม่ได้ผูกไว้แล้ว ฯลฯ )
- เชี่ยวชาญส่วนประกอบให้มากที่สุด (ตั้งค่า BindFlags ที่จำเป็นเท่านั้นเป็นต้น)
สิ่งนี้ทำให้ฉันสร้างสิ่งห่อหุ้มที่ซับซ้อนมากสำหรับการจัดการส่วนประกอบที่สร้างขึ้นและสถานะของการวางท่อในปัจจุบัน สิ่งนี้ไม่เพียงใช้เวลาในการพัฒนาที่มีค่าของฉันเท่านั้น แต่ยังเพิ่มความซับซ้อนอีกชั้นหนึ่ง
และที่เลวร้ายที่สุดของทั้งหมด: ฉันไม่รู้ด้วยซ้ำว่ามันคุ้มค่ากับปัญหาหรือไม่
ข้อควรพิจารณาในการปรับให้เหมาะสมของฉันบางอย่างอาจมีการใช้งานในระดับที่ต่ำกว่าและฉันเพิ่งทำซ้ำพวกเขาเพิ่มเวลาที่สูญเสียใน CPU การพิจารณาอื่น ๆ อาจไม่จำเป็นอย่างสมบูรณ์เนื่องจากผลกระทบต่อประสิทธิภาพการทำงานนั้นเล็กน้อย
ดังนั้นคำถามของฉันคือ:
- แนวทางใดข้างต้นที่ใช้ได้และฉันควรทำตามเท่าไหร่?
- GPU จัดการกับการเปลี่ยนแปลงสถานะอย่างไร
- จะเกิดอะไรขึ้นถ้าฉันเปลี่ยนสถานะที่ไม่เคยใช้ (ไม่มีการเรียกสายขณะที่ใช้งาน)
- บทลงโทษที่เกิดขึ้นจริงจากการผูกส่วนประกอบต่าง ๆ มีอะไรบ้าง?
- ข้อควรพิจารณาด้านประสิทธิภาพอื่น ๆ ที่ควรทำ
โปรดอย่าเพิ่งบอกฉันว่าฉันไม่ควรสนใจเรื่องการแสดงจนกว่าจะถึงขีด จำกัด ที่แท้จริง ในขณะที่เห็นได้ชัดว่าเป็นเรื่องจริงจากมุมมองของภาคปฏิบัติฉันให้ความสนใจในทฤษฎีเป็นหลัก ฉันต้องการต่อสู้กับการสร้างกรอบกราฟิกที่ดีที่สุดและฉันไม่คิดว่าฉันจะทำเช่นนั้นได้ด้วยการบรรยายเรื่อง
การจัดการส่วนประกอบ
ขณะนี้ฉันกำลังเขียนแอพพลิเคชั่น DirectX 11 ใน C # โดยใช้ SlimDX เป็น wrapper ที่มีการจัดการ มันเป็น wrapper ระดับต่ำมากและสิ่งที่เป็นนามธรรมในปัจจุบันของฉันถูกสร้างขึ้นบนมัน
มีข้อดีบางอย่างที่เห็นได้ชัดเมื่อใช้ Direct3D Abstraction การตั้งค่าสภาพแวดล้อมที่โหลด shaders การตั้งค่าคงที่และการวาดภาพตาข่ายง่ายมากและใช้มากน้อยรหัส นอกจากนี้เนื่องจากมันจัดการการสร้างและการกำจัดส่วนประกอบส่วนใหญ่จึงสามารถนำกลับมาใช้ใหม่ได้ทุกที่โดยอัตโนมัติและฉันเกือบจะหลีกเลี่ยงการรั่วไหลของหน่วยความจำได้อย่างสมบูรณ์
- โดยปกติคุณจะจัดการส่วนประกอบกราฟิกและทรัพยากรทั้งหมดอย่างไร
- คุณช่วยแนะนำ wrappers ที่มีการจัดการทำบางอย่างที่คล้ายกับตัวอย่างด้านล่างของฉันได้ไหม
นี่คือตัวอย่างของการใช้งานปัจจุบันของฉัน ฉันมีความสุขมากกับส่วนต่อประสาน มันมีความยืดหยุ่นเพียงพอสำหรับความต้องการของฉันและใช้งานและเข้าใจได้ง่ายมาก:
// 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();
}