सब कुछ के लिए उदाहरण का उपयोग कर?


16

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

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

तो मेरा सवाल यह है कि क्या इंस्टेंस का उपयोग करके किसी वस्तु का एक उदाहरण निकालना एक बुरा विचार है? क्या उदाहरण के लिए ओवरहेड (मेमोरी- और प्रदर्शन-वार) बहुत अधिक है या क्या यह किसी भी तरह से एकल-आवृत्ति ऑब्जेक्ट्स को प्रस्तुत करने के लिए अवांछित है?

जवाबों:


19

XPDM9 के तहत XPDM के साथ आप लगभग निश्चित रूप से जहाँ भी संभव हो, उदाहरण देना चाहते हैं। ड्रॉ कॉल ओवरहेड सिर्फ इतना अधिक है कि यह समझ में आता है। उस परिदृश्य में क्रॉसओवर-पॉइंट 2 या 3 उदाहरणों के रूप में कम हो सकता है।

यदि आपको किसी दिए गए जाल का केवल एक उदाहरण मिला है, तो यह सतह पर गैर-इंस्टेंस्ड को आकर्षित करने के लिए आकर्षक लग सकता है। हालांकि, इसमें शामिल होने पर गौर करें:

  • आपको shader constants अपलोड करने के लिए डेटा को प्रति-इंस्टेंट बफ़र में लोड करने से स्विच करने की आवश्यकता है।
  • आपको अपने शीर्ष की छाया की दो प्रतियां रखने की आवश्यकता है: एक उदाहरण के लिए और एक गैर-इंस्टेंट के लिए।
  • आपको अपने रेंडरिंग कोड की दो प्रतियां रखने की आवश्यकता है: इसी तरह।
  • आपको शेड्स स्विच करने की आवश्यकता है।
  • आपको वर्टेक्स स्वरूपों को स्विच करने की आवश्यकता है।
  • आपको शीर्ष बफ़र स्विच करने की आवश्यकता हो सकती है।
  • और फिर आपको इसे फिर से करने की ज़रूरत है यदि आप अगले समूह के मेषों के लिए ड्राइंग बनाने के लिए वापस जा रहे हैं।

यहां तक ​​कि अगर आपको केवल एक जाल मिला है (जैसे एफपीएस में बंदूक मॉडल की तरह) ऐसे मामले हैं जहां इंस्टेंस उपयोगी है। मान लीजिए कि आप आगे रेंडर में और जेड-प्रीपास के साथ मल्टीप्लस लाइट संचय कर रहे हैं। प्रत्येक प्रकाश के लिए एक अतिरिक्त पास के बजाय, आप अपनी रोशनी को प्रति-इंस्टेंस डेटा बनाते हैं और आप इसे इंस्टेंट बनाते हैं।

पहले परिदृश्य के आधार पर, कहानी का नैतिक आधार यह है कि यदि कोई भी वस्तु वर्ग सभी में इंस्टेंसिंग का उपयोग कर सकता है, तो यह समझ में आता है कि हमेशा उस क्लास के सभी ऑब्जेक्ट्स के लिए इंस्टेंसिंग का उपयोग करें।

दूसरे परिदृश्य के आधार पर, कहानी का नैतिक यह है कि इंस्टेंसेसिंग में गैर-स्पष्ट उपयोग हो सकते हैं जो सिर्फ यह कहकर परे जाते हैं कि "मुझे 20 पेड़ खींचने की आवश्यकता है"।


आपके द्वारा दिए गए कारण वही हैं जिन्होंने मुझे यह प्रश्न पहली जगह में पूछा था। धन्यवाद।
एनपीएस

12

(मेरे सिस्टम पर, कहीं और इसका परीक्षण नहीं किया) जीएल में, एक ही जाली (गिनती = 1 के साथ ड्राइंग) को उकसाना कुछ बुरा ओवरहेड है, लेकिन मुझे नहीं पता कि यह कहां से आता है। मैं दृढ़ता से यह नहीं करने का सुझाव देता हूं।

मैंने कुछ महीने पहले एक व्यावहारिक अनुप्रयोग में इसका परीक्षण किया था। मैंने क्रायटेक स्पोंज़ा दृश्य में कुछ वैश्विक रोशनी के एल्गोरिदम को कोडित किया, जिसमें लगभग 350 या तो मेष (ठीक से याद नहीं है) शामिल हैं, जिनमें से एक युगल कुछ उदाहरणों को साझा करता है। शुरुआत में मैंने ऐसा किया था जैसा कि आप सुझाव देते हैं, बस सब कुछ उदाहरण दें और बाकी को 1 की गिनती के साथ ड्रा करें, क्योंकि यह रेंडरिंग कोड को थोड़ा सरल करता है।

बाद में जब रेंडरर को अनुकूलित किया जाता है, तो बस गिनती = 1 वस्तुओं को वापस करने से पीछे हटने से उन्हें सामान्य तरीके से जमा करने से मुझे एक i7 3770k (और GTX 770) पर लगभग 3.5 मिलीसेकंड प्रति फ्रेम के समय की बचत होती है। केवल उन्हें पारंपरिक तरीके से करने के लिए कई उदाहरणों के साथ मेश को स्विच करना मुझे एक और 0.5ms बचाता है। कुल मिलाकर आवेदन ~ 120 FPS से लगभग ~ 230 FPS चला गया।

पाठ्यक्रम के ये आंकड़े हमेशा इस बात पर निर्भर करते हैं कि आपके आवेदन में अड़चनें कहां हैं, और बाद के 0.5ms वास्तव में एक ऐसे अनुप्रयोग में धीमे-धीमे हो सकते हैं, जहां आप बहुत आकर्षित हैं। लेकिन अन्यथा, मेरे अनुभव में उदाहरण के लिए कुछ खराब ओवरहेड हैं यदि आप एक बार में बहुत सारी चीजें नहीं खींच रहे हैं।


दिलचस्प है, लेकिन एएमडी और इंटेल ड्राइवरों के लिए डेटा देखना अच्छा होगा, अन्यथा, आपको वास्तव में "इन जीएल" के बजाय "मेरे सिस्टम पर" कहना चाहिए। दूसरी ओर, भले ही यह अन्य कार्यान्वयनों के साथ कोई समस्या नहीं है, यह तथ्य कि यह कुछ पर हो सकता है यदि आप इसका उपयोग नहीं कर रहे हैं तो इंस्टेंस से बचने के लिए पर्याप्त कारण है।
bcrist

2

आप इस बात के लिए निश्चित हो सकते हैं कि किसी एकल ऑब्जेक्ट को आरेखण करना सामान्य रूप से किसी एकल ऑब्जेक्ट को खींचने की तुलना में अधिक महंगा है। उदाहरण के लिए, GPU बड़ी मात्रा में वस्तुओं की तैयारी कर रहा है और यह तैयारी किसी एकल ऑब्जेक्ट की तुलना में भिन्न होगी। हालाँकि यह प्रदर्शन कितना बड़ा है, यह केवल प्रयोग करके पाया जा सकता है और यह आपके वास्तविक रेंडरिंग सेट-अप के आधार पर बहुत अधिक है। सुनिश्चित करने के लिए जानने का एकमात्र तरीका यह है कि आप स्वयं इसका परीक्षण करें। सिंगल ड्रॉ कॉल को बेंचमार्क करना कठिन है, आप कैसे आगे बढ़ सकते हैं, इस पर कई विचार हैं।


2

यह 4 साल हो गया है ... और मुझे लगता है कि यह कहना सुरक्षित है कि " इंस्टेंट " ड्रॉ के साथ कॉल करने के लिए पूरी तरह से ठीक है। जैसा कि आपने देखा हो सकता है, नए एपीआई DX12 और Vk दोनों का एक उदाहरण है जो 0 से हो सकता है। NUM_INSTANCES । यह भी ध्यान दें कि कोई ड्रॉइन्डेक्स्ड (...) नहीं है

संपादित करें

सावधानी के एक नोट के रूप में, उपरोक्त इस आधुनिक एपीआई के साथ शायद ठीक है, शायद कुछ पुराने जैसे ग्ल <3.3 या शायद डीएक्स 11 का उपयोग करके कुछ रूपरेखा की आवश्यकता होगी जैसा कि अन्य उपयोगकर्ताओं द्वारा उल्लेख किया गया है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.