बैचिंग प्रदर्शन में सुधार कैसे करें


9

मैं मोबाइल प्लेटफ़ॉर्म (एस) के लिए स्प्राइट आधारित 2 डी गेम विकसित कर रहा हूं और ग्राफिक्स रेंडर करने के लिए ओपनजीएल (अच्छी तरह से, वास्तव में इरक्लिक्ट) का उपयोग कर रहा हूं। पहले मैंने स्प्रैट रेंडरिंग को एक सरल तरीके से लागू किया: प्रत्येक गेम ऑब्जेक्ट को अपने स्वयं के GPU ड्रॉ कॉल के साथ क्वाड के रूप में प्रस्तुत किया जाता है, जिसका अर्थ है कि अगर मेरे पास 200 गेम ऑब्जेक्ट्स थे, तो मैंने प्रति फ्रेम 200 कॉल कॉल की। बेशक यह एक बुरा विकल्प था और मेरा गेम पूरी तरह से सीपीयू से बँधा हुआ था क्योंकि हर जीपीयू ड्रॉ कॉल में थोड़ा-बहुत सीपीयू ओवरहेड एसोसियेटेड होता है। GPU ज्यादातर समय निष्क्रिय रहा।

अब, मैंने सोचा कि मैं बड़े बैचों में वस्तुओं को इकट्ठा करके और केवल कुछ ड्रॉ कॉल के साथ इन बैचों को प्रस्तुत करके प्रदर्शन में सुधार कर सकता हूं। मैंने बैचिंग लागू की (ताकि हर गेम ऑब्जेक्ट एक ही बनावट को साझा करते हुए एक ही बैच में प्रस्तुत किया गया है) और सोचा कि मेरी समस्याएं दूर हो गई हैं ... केवल यह पता लगाने के लिए कि मेरी फ्रेम दर पहले की तुलना में भी कम थी।

क्यों? खैर, मेरे पास 200 (या अधिक) गेम ऑब्जेक्ट हैं, और वे प्रति सेकंड 60 बार अपडेट किए जाते हैं। हर फ्रेम मुझे सीपीयू में वर्टिकल के लिए नई स्थिति (अनुवाद और रोटेशन) को पुनर्गणना करना पड़ता है (मोबाइल प्लेटफॉर्म पर जीपीयू इंस्टेंटिंग का समर्थन नहीं करता है इसलिए मैं इसे वहां नहीं कर सकता), और यह गणना प्रति सेकंड 48000 (200 * 60 * 4) हर स्प्राइट में 4 वर्टीकल होते हैं) बस बहुत धीमा लगता है।

प्रदर्शन को बेहतर बनाने के लिए मैं क्या कर सकता था? सभी गेम ऑब्जेक्ट्स हर फ्रेम को घुमाते / घुमाते (लगभग) करते हैं इसलिए मुझे वास्तव में वर्टेक्स पोजीशन को रिकॉल करना है। केवल अनुकूलन जो मैं सोच सकता था कि रोटेशन के लिए एक लुक-अप तालिका है ताकि मुझे उनकी गणना न करनी पड़े। अंक स्प्राइट मदद करेगा? कोई गंदा हैक? और कुछ?

धन्यवाद।

जवाबों:


5

क्या तुमने प्रयोग किया Android के लिए irrlicht के मेरे पोर्ट का ? एंड्रॉइड और आईफोन पर 2 डी स्प्राइट्स के लिए, मैं आपके जैसे ही ट्रिक का उपयोग करता हूं: बैचिंग। मैं OpenGL ES 1.x और 2.x में कई समाधान आज़माता हूं:

  • z (लंबन) और बनावट के आधार पर, CPU पर रूपांतरण करें और glDrawArrays या glDrawElements (सबसे तेज़ तरीका) को कॉल करें। यदि आप कर सकते हैं तो एक बड़ी बनावट का उपयोग करें।
  • VBO के साथ एक ही चाल, तेजी से नहीं क्योंकि प्रत्येक फ्रेम के लिए आप सभी informations ताज़ा करते हैं। यह स्टैटिक्स स्प्राइट्स के लिए उपयोगी हो सकता है।
  • OpenGL ES 2.x का उपयोग करें और पदों की गणना (धीमी) करने के लिए वर्टेक्स शेडर का उपयोग करें
  • पॉइंटस्प्रिट्स का उपयोग करें (यदि कोई वर्ग नहीं है और बहुत सारे पारदर्शी पिक्सल फिलरेट को मारते हैं तो कोई समाधान नहीं)
  • gldrawtexoes एक्सटेंशन का उपयोग करें ...
  • प्रत्येक स्प्राइट के लिए एक ड्रैकल का उपयोग करें (सबसे धीमी विधि)

तो आप के रूप में, सभी परिवर्तन सीपीयू द्वारा ओजीएलईएस 1.x या ओजीएलईएस 2.x के लिए किए जाते हैं। यदि आपके पास नियोन निर्देश हैं, तो आप अपनी गणनाओं को गति देने के लिए उनका उपयोग कर सकते हैं।

Ps: iPhone या Android उपकरणों पर, मैं CPU सीमित नहीं हूं, लेकिन सीमित दर भरें। इसलिए ओवरड्रॉ को सीमित करना बहुत महत्वपूर्ण है।


बहुत बढ़िया, यह कुछ ऐसा है जिसकी मुझे तलाश थी। मुझे आपके Irrlicht पोर्ट के बारे में पता नहीं था लेकिन मेरे पास पहले से ही iOS पर चलने वाले Irrlicht का मेरा संस्करण है। आप कहते हैं कि आप सीपीयू सीमित नहीं हैं - आप कितने स्प्राइट ड्राइंग कर रहे हैं? और iPhone पर 100 स्प्राइट्स के लिए, आपके फ्रैमरेट्स क्या कहते हैं? अगर मेरे पास 200 वस्तुएं हैं, तो मैं प्रति सेकंड 48000 गणनाएं करता हूं। भराव के बारे में आपकी बात अच्छी है।
user4241

स्थैतिक स्प्राइट (पृष्ठभूमि) वीबीओ में हैं। मैं प्रति लंबन एक VBO का उपयोग करता हूं। अन्यथा, मेरे पास मोबॉक्स पर 100 से 200 स्प्राइट हैं। 3G सहित सभी iphones पर, मेरे पास 30fps (जैसा मुझे याद है) से अधिक है। लेकिन बड़े स्प्राइट बहुत महंगे हैं (समस्या को भरने के लिए) ....
एलिस

मैं एक कण इंजन पर काम कर रहा हूं, जिसका उपयोग मैं CPU पर किए गए सभी पदों के साथ 20 000 तक कण कर सकता हूं और मेरे पास चरम सेटिंग्स (3GS और iPhone4 पर) के साथ 10fps है। इसलिए अच्छे फ्रैमरेट के साथ 3GS या iPhone4 पर 1000 स्प्राइट्स संभव हैं।
एलिस

धन्यवाद, बहुत मददगार! आप अपने कण इंजन को कैसे लागू कर रहे हैं? मुझे लगता है कि आप shaders के साथ खेल रहे हैं?
user4241

मैं shaders का उपयोग करता हूं क्योंकि मुझे प्रत्येक कण आकार को सेटअप करने के लिए gl_PointSize की आवश्यकता है। मैं OGLES 1.x के साथ अब काम नहीं करता क्योंकि पुराने फोन मेरा लक्ष्य नहीं हैं। पहले, मेरा सभी कोड OGLES 1.x था, फिर OGLES 1.x और OGLES 2.x (कोई प्रदर्शन सुधार नहीं) और अब OGLES 2.x (सुधार सुधार)।
एलिस

1

मैं एक वीबीओ रखने की सलाह दूंगा, जिसमें प्रत्येक शीर्ष पर स्थिति / प्रत्येक प्रदान की गई वस्तु के रोटेशन और बनावट के आधार पर बैचिंग होगी जैसे आप कर रहे हैं। मैं ogl ES से बहुत परिचित नहीं हूँ, इसलिए मुझे यकीन नहीं है कि यह glsl के किस संस्करण का समर्थन करता है, लेकिन आप शायद एक सेट के आधार पर बैच कर सकते हैं, और जो 4 या तो बनावट आप पास कर रहे हैं में आप शीर्ष के अंदर का उपयोग कर रहे हैं। प्वाइंट स्प्राइट्स निश्चित रूप से आपके प्रदर्शन में सुधार करेंगे, क्योंकि यह आपके द्वारा भेजे जा रहे डेटा की मात्रा में कटौती करेगा, और यदि आप इसे सही तरीके से कर रहे हैं तो बैचिंग को कभी भी प्रदर्शन में कमी नहीं करनी चाहिए। इसके अलावा, आप शेडर पर रोटेशन की गणना करके प्रदर्शन को थोड़ा बेहतर कर सकते हैं और केवल इंट्स / फ्लोट वैल्यू में पासर्स में या वर्टेक्स के अंदर ही पास हो सकते हैं। (अधिक तेज़ हो जाएगा,


आपके उत्तर के लिए धन्यवाद। शेडर में रोटेशन गणना करने के बारे में आपका सुझाव एक्सलेट है लेकिन दुर्भाग्य से मैं ओपनजीएल ईएस 1 का उपयोग कर रहा हूं जो शेड्स का समर्थन नहीं करता है इसलिए मैं निश्चित पाइप लाइन के साथ फंस गया हूं। मैं पॉइंट स्प्राइट की कोशिश करूँगा लेकिन मैं उन्हें सभी मामलों में उपयोग नहीं कर सकता क्योंकि उनके आकार की ऊपरी सीमा है। मैं अभी भी वीबीओ के बारे में थोड़ा निराशावादी हूं, अगर मैं प्रत्येक फ्रेम में प्रत्येक शीर्ष की स्थिति का पुनर्गणना कर रहा हूं, तो वीबीओ कैसे मदद करता है?
user4241

यह आपके शीर्ष डेटा को gpu पर बने रहने की अनुमति देता है, जिससे आपको प्रत्येक फ़्रेम पर gpu को भेजे जाने वाले डेटा की मात्रा घट जाती है। इस थियो का लाभ उठाने के लिए आपको शेड्स की आवश्यकता नहीं है, आपको वर्टेक्स डेटा को बिल्कुल भी बदलने की आवश्यकता नहीं है, यदि आपके पास प्रत्येक स्प्राइट के लिए आधार स्थिति (जैसे मूल) है, तो आप बस वर्ल्ड मैट्रिक्स को बदल सकते हैं कॉल ड्रॉ होने से पहले यह रूपांतरित हो जाता है। हालाँकि, यह कठिन हो सकता है जब बैचिंग। निश्चित फ़ंक्शन का उपयोग करते हुए, यह केवल वीबीओ पर स्विच करने और कम से कम अब के लिए बैचिंग को छोड़ने के लिए अधिक फायदेमंद होगा, यह निश्चित रूप से आपको बढ़ावा देगा।
sringer

में तुम्हारी बात समझ रहा हूँ। तो आखिरकार, आप बैचिंग के बारे में बात नहीं कर रहे हैं, लेकिन एक गेम ऑब्जेक्ट को खींचने के लिए बस एक ड्रॉ कॉल का उपयोग कर रहे हैं। मैं निश्चित रूप से परीक्षण करूंगा कि बिना बैचिंग के वीबीओ मेरे खेल में एफपीएस को कैसे प्रभावित करता है लेकिन फिर भी प्रति फ्रेम 200 कॉल बहुत बड़ी लगती हैं ... लेकिन मुझे लगता है कि मुझे इसके साथ रहना होगा। यदि कोई अन्य उत्तर नहीं दिखाएगा तो मैं आपके उत्तर को स्वीकार करूंगा।
user4241

1

आप उन मोबाइल प्लेटफ़ॉर्म का उल्लेख करते हैं, जिनमें इंस्टेंस नहीं है। लेकिन, आप अभी भी शीर्ष shaders है, क्या तुम नहीं?

उस मामले में, आप अभी भी छद्म इंस्टेंसिंग कर सकते हैं, जो बहुत तेज़ है। कोने बिंदुओं के साथ एक VBO (GL_STATIC_DRAW) बनाएं (स्प्राइट के केंद्र बिंदु के सापेक्ष, जैसे -1 / -1, 1 / -1, 1/1, -1/1) और किसी भी बनावट को आपकी आवश्यकता के अनुसार, इसमें सम्मिलित करें ।
फिर स्प्राइट के केंद्र बिंदु पर प्रत्येक ड्रॉ कॉल के लिए सामान्य वर्टेक्स विशेषताओं में से एक को सेट करें, और बफर के साथ दो त्रिकोणों को बांधें। वर्टेक्स शेडर के अंदर, जेनेरिक वर्टेक्स विशेषता को पढ़ें और वर्टेक्स के निर्देशांक जोड़ें।

यह आपको हर स्प्राइट के लिए डेटा ट्रांसफर पर ब्लॉक करने से बचाएगा और ज्यादा तेज होना चाहिए। ड्रॉ कॉल की वास्तविक संख्या इतनी महत्वपूर्ण नहीं है, बीच में अवरुद्ध / रोक रहा है।


यह OpenGL ES 2.0 के लिए अच्छा समाधान लगता है। दुर्भाग्य से मैं ES 1 का उपयोग कर रहा हूं जिसमें शेड्स बिल्कुल नहीं हैं।
user4241

0

समस्या उस डेटा की मात्रा में रहती है जिसे आप प्रत्येक फ्रेम में GPU पर भेज रहे हैं। बस प्रत्येक बैच के लिए एक VBO बनाएं और इसे एक बार पॉपुलेट करें, फिर बैचों को ड्रा करते समय संबंधित ट्रांसफॉर्मेशन मेट्रिसेस (glMultMatrix के माध्यम से, या यदि आप ES 2.0 का उपयोग कर रहे हैं तो एक शेडर) को लागू करें।


मुझे समझ में नहीं आता है कि जब मैं अद्वितीय परिवर्तनों के साथ 200 अलग-अलग गेम ऑब्जेक्ट की मदद करता हूं तो यह कैसे मदद करता है? GlMultMatrix का उपयोग करना सभी वस्तुओं पर एक ही परिवर्तन लागू करेगा जो कि मैं नहीं चाहता। इसके अलावा, GPU को डेटा भेजना अड़चन नहीं है; अगर मैं CPU- साइड ट्रांसफ़ॉर्मेशन को हटाता हूं तो परफ्यूम बहुत अच्छा है।
user4241

हां, लेकिन अगर सही तरीके से लागू किया जाए तो एक वीबीओ प्रदर्शन में सुधार कर सकता है। वर्तमान में आप अपनी 200 वस्तुओं को कैसे प्रस्तुत कर रहे हैं? क्या आप glBegin / glEnd का उपयोग कर रहे हैं?
बूज़सॉ

1
मैं कस्टम दृश्य नोड के साथ Irrlicht 3D इंजन का उपयोग कर रहा हूं, इसलिए मैं सीधे OpenGL का उपयोग नहीं कर रहा हूं (लेकिन मुझे लगता है कि यह इस मामले में सरल glBegin / glEnd का उपयोग कर रहा है)। क्या VBO वास्तव में मदद करेगा क्योंकि मुझे हर फ्रेम में पूरे बफर को संशोधित करना होगा? इसके अलावा, यह सीपीयू-बाउंड होने के बारे में मौलिक समस्या का समाधान नहीं करता है क्योंकि वर्टेक्स ट्रांसफ़ॉर्मेशन की गणना है। लेकिन फिर भी आप अपने जवाब के लिए धन्यवाद!
15
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.