मैं अक्सर ग्राफिक्स के साथ काम करते समय बहुत अधिक समयपूर्व अनुकूलन करता हूं। कुछ सिद्धांत हैं जिनका मैं हमेशा पालन करने की कोशिश करता हूं:
- डी 3 डी घटकों की संख्या को न्यूनतम रखें। (रेंडर स्टेट्स, बफ़र्स, शेड्स इत्यादि)
- यदि आवश्यक हो तो केवल घटकों को बांधें। (पहले से बाध्य नहीं, आदि)
- जितना संभव हो उतना घटकों को विशेष करें। (केवल आवश्यक BindFlags आदि सेट करें)
यह मुझे निर्मित घटकों और वर्तमान पाइपिंग स्थिति के प्रबंधन के लिए बहुत विस्तृत आवरण बनाने की ओर ले जाता है। न केवल यह मेरे मूल्यवान विकास के समय का बहुत अधिक उपभोग करता है, यह जटिलता की एक और बड़ी परत को भी जोड़ता है।
और सबसे बुरा: मुझे नहीं पता कि क्या यह परेशानी के लायक है।
मेरे कुछ अनुकूलन के विचार पहले से ही निचले स्तर पर लागू हो सकते हैं और मैं सिर्फ उन्हें दोहरा रहा हूं, इसके अलावा सीपीयू पर समय बर्बाद कर रहा हूं। अन्य विचार पूरी तरह से अनावश्यक हो सकते हैं, क्योंकि प्रदर्शन पर प्रभाव नगण्य है।
तो मेरे सवाल हैं:
- उपरोक्त दिशानिर्देशों में से कौन सा मान्य है और मुझे उनका पालन किस सीमा तक करना चाहिए?
- जीपीयू की स्थिति कैसे बदलती है?
- अगर मैं कभी इस्तेमाल नहीं होने वाले राज्य को बदल दूं तो क्या होगा? (सक्रिय होने पर कोई ड्रा कॉल नहीं किया जा रहा है।)
- विभिन्न विभिन्न घटकों को बांधने के लिए वास्तविक प्रदर्शन दंड क्या हैं?
- अन्य प्रदर्शन पर क्या विचार किया जाना चाहिए?
कृपया मुझे यह न बताएं, कि मुझे केवल प्रदर्शन की परवाह नहीं करनी चाहिए, जब तक कि मैं वास्तविक सीमाओं को नहीं मारूं। जबकि यह स्पष्ट रूप से एक व्यावहारिक दृष्टिकोण से सच है, मुझे मुख्य रूप से सिद्धांत में दिलचस्पी है। मुझे किसी तरह से इष्टतम ग्राफिक्स ढांचे के निर्माण के आग्रह का मुकाबला करने की आवश्यकता है और मुझे नहीं लगता कि मैं सामान्य रूप से "समय से पहले अनुकूलन व्याख्यान" के साथ ऐसा कर सकता हूं।
घटकों का प्रबंधन
मैं वर्तमान में C # को एक प्रबंधित रैपर के रूप में SlimDX का उपयोग करके DirectX 11 अनुप्रयोग लिख रहा हूं। यह बहुत निम्न स्तर का आवरण है और इसके ऊपर मेरा वर्तमान अमूर्त बनाया गया है।
Direct3D अमूर्त का उपयोग करते समय कुछ स्पष्ट फायदे हैं। पर्यावरण की स्थापना, लोडिंग शेड्स, स्थिरांक स्थापित करना और एक जाल खींचना बहुत सरल है और बहुत कम कोड का उपयोग करता है । इसके अलावा, चूंकि यह अधिकांश घटकों के निर्माण और निपटान का प्रबंधन करता है, इसलिए वे हर जगह स्वचालित रूप से पुन: उपयोग किए जा सकते हैं और मैं मेमोरी लीक से लगभग पूरी तरह से बचता हूं।
- आप आमतौर पर सभी ग्राफिक्स घटकों और संसाधनों का प्रबंधन कैसे करते हैं?
- क्या आप मेरे उदाहरण के समान कुछ प्रबंधित रैपर की सिफारिश कर सकते हैं?
यहाँ मेरे वर्तमान कार्यान्वयन का एक उदाहरण है। मैं इंटरफेस से काफी खुश हूं। इसमें मेरी जरूरतों के लिए पर्याप्त लचीलापन है और यह उपयोग करने और समझने के लिए बहुत सरल है:
// 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();
}