2012-06-26 13 views
14

मेरे आवेदन में मैं बड़े पैमाने पर glTexImage2D का उपयोग कर रहा हूं। मैं एक छवि की कुछ छवि कॉपी करता हूं और इसे एक बनावट के रूप में प्रस्तुत करता हूं, मैं इसे हर माउस क्लिक पर अक्सर करता हूं। मैं इसे प्रतिपादन के लिए बाइट सरणी के रूप में देता हूं। स्मृति खाई जा रही है और स्वैप मेमोरी भी आवंटित की जाती है। क्या यह एक स्मृति रिसाव है? या यह इस तथ्य के कारण है कि glTexImage2D में कोई संदर्भ या कुछ और है।opengl में बनावट के साथ स्मृति का प्रबंधन कैसे करें?

संपादित करें:

//I allocate the memory once 
    GLuint texName; 
    texture_data = new GLubyte[width*height]; 

    // Each time user click I repeat the following code (this code in in callback) 
    // Before this code the texture_data is modified to reflect the changes 
    glGenTextures(3, &texname); 
    glBindTexture(GL_TEXTURE_2D, texname); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE,texture_data); 

मैं अपने करीबी अनुरोध आशा और मतदान नीचे अब बंद कर देंगे!

+2

वास्तविक कोड इस समस्या को ट्रैक करने में सहायक होगा। –

+0

@ निकोलबोलस, मैंने कोड डाला है, +1 – Shan

उत्तर

40

मान लें कि आप glGenTextures के साथ glTexImage2D पर कॉल करते समय एक नया बनावट बना रहे हैं, तो आप स्मृति को बर्बाद कर रहे हैं, और यदि आप उत्पन्न होने वाले सभी बनावटों का ट्रैक न रखें तो इसे लीक करें। glTexImage2D इनपुट डेटा लेता है और इसे वीडियो कार्ड मेमोरी स्टोर करता है। glTexImage2D पर कॉल करने से पहले आप जिस बनावट को बांधते हैं - glGenTextures के साथ जेनरेट करने वाला एक वीडियो कार्ड मेमोरी के उस हिस्से के लिए एक हैंडल है।

यदि आपका बनावट बड़ा है और आप इसे हर बार उपयोग करते समय इसकी अधिक से अधिक प्रतियों को स्टोर करने के लिए नई मेमोरी आवंटित कर रहे हैं, तो आप जल्दी से स्मृति से बाहर हो जाएंगे। समाधान आपके आवेदन के प्रारंभ के दौरान glTexImage2D पर कॉल करना है और जब आप इसका उपयोग करना चाहते हैं तो केवल glBindTexture पर कॉल करें। यदि आप क्लिक करते समय बनावट को स्वयं बदलना चाहते हैं, तो केवल glBindTexture और glTexImage2D पर कॉल करें। यदि आपकी नई छवि पिछले छवि के समान आकार है, तो आप इसे हटाने और नए अपलोड करने के बजाय पुराने छवि डेटा को ओवरराइट करने के लिए ओपनजीएल को बताने के लिए glTexSubImage2D पर कॉल कर सकते हैं।

अद्यतन

अपने नए कोड के जवाब में, मैं एक अधिक विशिष्ट जवाब के साथ अपने जवाब को अद्यतन करने कर रहा हूँ। आप ओपनजीएल बनावट से पूरी तरह गलत तरीके से काम कर रहे हैं glGenTextures का आउटपुट GLuint[] है और String या char[] नहीं है। glGenTextures के साथ उत्पन्न हर बनावट के लिए, ओपनजीएल आपको एक बनावट (एक हस्ताक्षरित पूर्णांक के रूप में) को बनावट में वापस देता है। यह संभाल उस स्थिति को संग्रहीत करता है जिसे आप glTexParameteri के साथ ग्राफिक्स कार्ड पर स्मृति का एक हिस्सा देते हैं, यदि आप इसे glTexImage[1/2/3]D के साथ डेटा देते हैं। जब आप इसे अपडेट करना चाहते हैं तो हैंडल को स्टोर करने और इसे नया डेटा भेजने के लिए आप पर निर्भर है। यदि आप हैंडल को ओवरराइट करते हैं या इसके बारे में भूल जाते हैं, तो डेटा अभी भी ग्राफिक्स कार्ड पर रहता है लेकिन आप इसका उपयोग नहीं कर सकते हैं। आप यह भी कह रहे हैं ओपन 3 बनावट उत्पन्न करने के लिए जब आप केवल 1.

रूप texture_data एक निश्चित आकार की है, तो आप glTexSubImage2D बजाय glTexImage2D साथ बनावट को अपडेट कर सकते देखकर जरूरत है। इस समस्या से स्मृति रिसाव से बचने के लिए यहां आपका कोड संशोधित किया गया है:

texture_data = new GLubyte[width*height](); 
GLuint texname; //handle to a texture 
glGenTextures(1, &texname); //Gen a new texture and store the handle in texname 

//These settings stick with the texture that's bound. You only need to set them 
//once. 
glBindTexture(GL_TEXTURE_2D, texname); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

//allocate memory on the graphics card for the texture. It's fine if 
//texture_data doesn't have any data in it, the texture will just appear black 
//until you update it. 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, 
    GL_UNSIGNED_BYTE, texture_data); 

... 

//bind the texture again when you want to update it. 
glBindTexture(GL_TEXTURE_2D, texname); 
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, 0, GL_RGB, 
    GL_UNSIGNED_BYTE, texture_data); 

... 

//When you're done using the texture, delete it. This will set texname to 0 and 
//delete all of the graphics card memory associated with the texture. If you 
//don't call this method, the texture will stay in graphics card memory until you 
//close the application. 
glDeleteTextures(1, &texname); 
+0

का उल्लेख करने के लिए धन्यवाद धन्यवाद, मैंने कोड पोस्ट किया है, इसलिए आप देख सकते हैं कि मैं एक ही मेमोरी का उपयोग करता हूं, बस सामग्री को बदलता हूं और हमेशा वही करता हूं। तो उपरोक्त कोड स्निपेट में आपके सुझाव के अनुसार मुझे केवल "glGenTextures" को कॉल करने की आवश्यकता है और फिर हमेशा glBindTexture और glTexImage2D को कॉल करें। यह स्मृति रिसाव को रोक देगा। क्या मैं सही हूँ? – Shan

+1

@Shan ने कोड के साथ अपना जवाब अपडेट किया और (उम्मीद है कि) पर्याप्त स्पष्टीकरण ताकि आप समझ सकें कि आपके कोड के भीतर रिसाव कहां से आ रहा है और इसे कैसे ठीक किया जाए। भविष्य में ओपनजीएल मैनुअल का भी उपयोग करें, ओपनजीएल विधियों के बारे में समझाते हुए यह बहुत उपयोगी है: http://www.opengl.org/sdk/docs/man/xhtml/glGenTextures.xml –

+0

बहुत बहुत धन्यवाद, उत्कृष्ट जवाब!, असल में मैंने कोड अपडेट किया है, यह गड़बड़ हो गया है, प्रकार texname के लिए GLuint है। बस एक प्रश्न, मेरे पास एक से अधिक बनावट हैं, gltexSubImage2D कैसे पता चलेगा कि मैं कौन सा अपडेट कर रहा हूं? या यह glbindTexture के लिए कॉल के कारण है। – Shan

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