2015-10-16 4 views
7

पिक्सलशैडर का उपयोग करने के लिए माइक्रोसॉफ्ट के example में वे एक सिंगलटन का उपयोग करते हैं। मैंने other places में एक ही पैटर्न देखा है, और यहां वे कहते हैं किएक सिंगलटन पिक्सेलशैडर का उपयोग करना चाहिए सबसे अच्छा अभ्यास?

पिक्सेल शेडर एक निजी स्थैतिक क्षेत्र _pixelShader में संग्रहीत है। यह क्षेत्र स्थैतिक है, क्योंकि संकलित शेडर कोड का एक उदाहरण पूरे वर्ग के लिए पर्याप्त है।

हमने इस पैटर्न का उपयोग करते समय कई मेमोरी लीक मुद्दों को देखा है। पिक्सेलशैडर शामिल है इवेंट हैंडलिंग जो हमेशा सही ढंग से साफ़ नहीं होता है। हमें freeze उन्हें था, और कुछ सुधार देखा। हमें मैन्युअल रूप से कुछ डिटेचमेंट

 // Attach/detach effect as UI element is loaded/unloaded. This avoids 
     // a memory leak in the shader code as described here: 
     element.Loaded += (obj, args) => 
     { 
      effect.PixelShader = ms_shader; 
      element.Effect = effect; 
     }; 
     element.Unloaded += (obj, args) => 
     { 
      effect.PixelShader = null; 
      element.Effect = null; 
     }; 

और अभी भी तनाव के तहत उस क्षेत्र में मेमोरी लीक अभी भी हैं। क्या किसी को पता है कि पिक्सेलशैडर एक सिंगलटन का उपयोग करने में परेशानी के लायक भारी संसाधनों का उपयोग करता है?

उत्तर

1

निश्चित रूप से नहीं। हालांकि, कारण PixelShader के साथ नहीं है, लेकिन इसका उपयोग ShaderEffect में है।
WPF के लिए कस्टम शेडर प्रभावों के लगभग सभी कार्यान्वयन माइक्रोसॉफ्ट के .NET 3.5 नमूने पर आधारित हैं, जिन्हें .NET 4.0 के लिए अपडेट नहीं किया गया था। सभी प्रभावों के लिए सिंगलटन PixelShader उदाहरण का उपयोग करना ठीक था, जो केवल ps_2_0 शेडर्स का समर्थन करता था। .NET 4.0 के साथ माइक्रोसॉफ्ट ने ps_3_0 पिक्सेल शेडर्स (जीपीयू-त्वरित उपकरणों के लिए) के लिए समर्थन प्रस्तुत किया, और इसके साथ, उन्होंने मेमोरी लीक को ShaderEffect कक्षा में पेश किया।
ShaderEffect अपनी PixelShader संपत्ति को ट्रैक करता है और यह जांचता है कि यह psix_0 बाइटकोड के लिए ps_3_0 रजिस्टरों का उपयोग नहीं करता है, जिसे पिक्सेलशैडर के आंतरिक ईवेंट _shaderBytecodeChanged कहा जाता है। इसलिए, सिंगलटन PixelShader एकाधिक ShaderEffect उदाहरणों द्वारा उपयोग किया जाता है, जीसी के लिए डोमिनिनेट रूट के रूप में कार्य करता है और सभी ऑब्जेक्ट्स को रेट करता है जिनका उपयोग ShaderEffect के किसी भी उदाहरण के साथ किया जाता था। वह known memory leak है, जो तय नहीं किया जाएगा।
आप लीक बिना सिंगलटन के रूप में PixelShader उपयोग करना चाहते हैं, तो आप क्रम हैकिंग का उपयोग करना होगा: हर बार PixelShader उदाहरण ShaderEffect वर्ग के PixelShader संपत्ति को सौंपा गया है, PixelShader उदाहरण के _shaderBytecodeChanged क्षेत्र मैन्युअल रूप से मंजूरी दे दी जानी चाहिए, जैसे:

var ei = typeof(PixelShader).GetEvent("_shaderBytecodeChanged", 
      BindingFlags.Instance | BindingFlags.NonPublic); 
var fi = typeof(PixelShader).GetField(ei.Name, 
       BindingFlags.Instance | BindingFlags.NonPublic); 
fi.SetValue(pixelShader,null); 

बेशक, इन परिचालनों को DynamicMethod आधारभूत संरचना या इसी तरह के तंत्र द्वारा रनटाइम में सहायक तरीके उत्पन्न करके अनुकूलित किया जा सकता है। हालांकि, इसका उपयोग केवल उन शेडरों के लिए किया जाना चाहिए जो निश्चित रूप से ps_2_0 हैं या निश्चित रूप से ps_3_0

संबंधित मुद्दे