2013-04-22 30 views
4

我們有一個應用程序,我們可以在OpenGL ES 2.0中繪製很多事物(主要是OpenStreetMap Tiles,但也包括其他圖像)。這很好,但時不時的應用程序崩潰沒有任何信息 - 這意味着:該應用程序只是關閉,而不是一個消息,它崩潰,也沒有消息在logcat。Android設備上的OpenGL中正確的內存管理

從我們已經想通了實驗,這在三星galaxy S3加載了太多的紋理轉換成OpenGL(glGenTextures/glBindTexture) 在實驗後的應用程序崩潰,我們能夠裝載1800個紋理與大小256×256 RGB888標準。之後,我們的應用程序崩潰,沒有任何錯誤日誌。當我們在加載紋理的同時不斷檢查OpenGL錯誤(GLES20.glGetError)時,是否應該收到錯誤(GL_OUT_OF_MEMORY)?

一般問的問題: 有沒有辦法確定gpu內存中可用的最大大小,或者至少,我們在內存不足時會如何得到警告? (問題是我們不知道什麼時候我們應該開始刪除句柄,並且我們希望儘可能多地保留它們......)

在此先感謝您的答覆。

回答

13

因此經過一番研究,我們找到了解決方案。

但首先: These methods不會幫助,或者不會these。 在第一篇文章中提到的方法會給你絕對無用的數字,它根本不會幫助你,甚至可能不是正確的(因爲我的galaxy S3比nexus 7的數量多得多。但是在我們的測試中,nexus 7可以加載與S3相同的量或更多的紋理)。

那就讓我們繼續我們的解決方案 - 這是我們仍然不能肯定是最好的,但它的工作:

它看起來喜歡你可以保持儘可能多的紋理在OpenGL中,你有免費的RAM總量。是的總RAM,而不是堆,而不是其他與你的應用程序相關的東西!這實際上是整個系統的可用內存量,沒有任何限制!

所以一旦你明白這一點,你剛纔讀出的可用內存量您有:

ActivityManager actvityManager = (ActivityManager) mapView.getActivity().getSystemService(Activity.ACTIVITY_SERVICE); 
ActivityManager.MemoryInfo mInfo = new ActivityManager.MemoryInfo(); 
actvityManager.getMemoryInfo(mInfo); 
Log.v("neom","mema " + mInfo.availMem/1024/1024); 

最好的地方,這樣做可能是您的onSurfaceCreated方法或somethign這樣。 您獲得的內存量是您當前擁有的可用內存總量。大多數情況下,這個值太低,幾乎在任何情況下,你甚至可以分配更多的內存(在我們的測試中,我們總是可以分配比availMem提供的內存多30%-50%的內存,直到應用程序崩潰爲止(在Nexus上測試7(+ 28%),Galaxy S3(+ 36%),變壓器T1(+ 57%),Nexus S(+ 57%)))。原因是:在內存真正用完之前,Android會從未使用的內容,後臺進程等中釋放內存。

那麼這是什麼意思?

您可以(幾乎)在OpenGL中安全地保留許多「字節紋理」,因爲您擁有可用的RAM。例如:假設你有375 MB可用RAM和每個大小爲256kb的紋理,你可以在OpenGL中保留大約1500個紋理,然後開始刪除它們中的一些(使用LRU緩存或類似的東西)。你甚至可以保持更多,但我認爲你這個數量是相當安全的。

Sureley你也可以得到availmem更加頻繁,只是適合你的緩存大小或什麼都你正在做的內存這個新的量 - 但我認爲,如果你在onSurfaceCreated做一次就足夠了 - 尤其是因爲這將是如果您切換到另一個應用程序並返回,請再次閱讀。

+0

尼斯調查。這可能是對的。使用單個「ByteBuffer」數百次調用'glBufferData'時,'availMem'略有減少。即使在手動GC之後,它也沒有增加。但直到'availMem'用完時才能分配。剩餘一點時系統已停止。也許對此有一些詳細的限制。 – donggas90 2017-01-07 18:51:39