ใช้การสร้างอินสแตนซ์สำหรับทุกสิ่งหรือไม่


16

อินสแตนซ์ช่วยเพิ่มประสิทธิภาพ (อย่างมีนัยสำคัญ) เมื่อเรนเดอร์หลายชุด แต่มันมีค่าใช้จ่ายเท่าไหร่เมื่อแสดงสำเนาหนึ่งชุดด้วยการเรียกแบบดึงครั้งเดียว เป็นความคิดที่ดีหรือไม่ดีที่จะใช้อินสแตนซ์สำหรับรูปทรงเรขาคณิตทั้งหมดของเครื่องยนต์

แก้ไข: สมมติว่าเรากำลังสร้างเกม FPS วัตถุส่วนใหญ่มีเพียงตัวอย่างเดียว: มีด, ปืน, ปืนกล, อาคารและหอวิทยุ แต่ยังมีวัตถุบางอย่างที่มีหลายอินสแตนซ์: ต้นไม้ (เช่น 3 ชนิดของต้นไม้ที่มีหลายร้อยอินสแตนซ์) หญ้าและอื่น ๆ ... สิ่งที่ฉันหมายถึงคือ: แทนที่จะแสดงวัตถุแบบเดียวกับวิธี "ดั้งเดิม" และต้นไม้ และหญ้าโดยใช้อินสแตนซ์เราแสดงผลทั้งหมดโดยใช้อินสแตนซ์ ดังนั้นหอวิทยุของเรามีเพียงหนึ่งตัวอย่าง (ที่มีข้อมูลที่เราเก็บไว้ในบัฟเฟอร์ข้อมูลเป็นต้น) และเราทำให้หอว่าการใช้ชนิดของการโทรกับอินสแตนซ์นับเท่ากับDrawInstanced() 1เช่นเดียวกับวัตถุอื่น ๆ (แน่นอนต้นไม้และหญ้ามีหลายกรณี)

ดังนั้นคำถามของฉันคือ: มันเป็นความคิดที่ดีที่จะวาดอินสแตนซ์เดียวของวัตถุโดยใช้อินสแตนซ์หรือไม่? การอินสแตนซ์มีค่าใช้จ่ายมากเกินไป (หน่วยความจำและประสิทธิภาพการทำงานที่ฉลาด) หรือเป็นสิ่งที่ไม่พึงประสงค์ในการเรนเดอร์วัตถุอินสแตนซ์เดี่ยวหรือไม่?

คำตอบ:


19

ภายใต้ D3D9 ด้วย XPDM คุณเกือบจะต้องการตัวอย่างทุกที่ที่ทำได้ ค่าใช้จ่ายในการเรียกเลขหมายสูงมากจนสมเหตุสมผล ในสถานการณ์นั้นครอสโอเวอร์ - พอยต์อาจต่ำได้ถึง 2 หรือ 3 อินสแตนซ์

หากคุณมีตัวอย่างตาข่ายที่ระบุเพียงครั้งเดียวมันอาจจะดูเหมือนว่าการดึงดูดให้มันไม่ใช่แบบอินสแตนซ์ อย่างไรก็ตามดูสิ่งที่เกี่ยวข้อง:

  • คุณต้องเปลี่ยนจากการโหลดข้อมูลไปยังบัฟเฟอร์ต่อหนึ่งอินสแตนซ์เป็นการอัปโหลดค่าคงที่ของ shader
  • คุณต้องเก็บสำเนาจุดสุดยอดของคุณสองชุด: สำเนาหนึ่งสำหรับแบบอินสแตนซ์และแบบหนึ่งสำหรับแบบที่ไม่ใช่อินสแตนซ์
  • คุณต้องเก็บรหัสการแสดงผลสองชุด: เช่นเดียวกัน
  • คุณต้องสลับเฉดสี
  • คุณต้องเปลี่ยนรูปแบบจุดสุดยอด
  • คุณอาจจำเป็นต้องเปลี่ยนบัฟเฟอร์จุดสุดยอด
  • แล้วคุณต้องทำมันอีกครั้งถ้าคุณกลับไปวาดรูปแบบอินสแตนซ์สำหรับกลุ่มตาข่ายต่อไป

แม้ว่าคุณจะมีตาข่ายเพียงอันเดียว (เช่นโมเดลปืนใน FPS) มีบางกรณีที่การใช้อินสแตนซ์นั้นมีประโยชน์ สมมติว่าคุณกำลังทำการสะสมแสงแบบมัลติพลาสเตอร์ในโหมดเรนเดอร์ฟอร์แมตและกับ z-prepass แทนการผ่านพิเศษสำหรับแสงแต่ละดวงคุณทำให้ไฟของคุณต่อข้อมูลอินสแตนซ์และคุณวาดมันขึ้นมา

ขึ้นอยู่กับสถานการณ์แรกคุณธรรมของเรื่องราวคือถ้าคลาสวัตถุใด ๆ สามารถใช้การอินสแตนซ์ได้ทั้งหมดมันทำให้รู้สึกถึงการใช้อินสแตนซ์สำหรับวัตถุทั้งหมดของคลาสนั้น

ตามสถานการณ์ที่สองคุณธรรมของเรื่องราวคือการใช้อินสแตนซ์ไม่สามารถใช้งานได้อย่างชัดเจนซึ่งนอกเหนือไปจากการพูดว่า "ฉันต้องวาด 20 ต้น"


เหตุผลที่คุณให้เป็นเหตุผลเดียวกันกับที่ทำให้ฉันถามคำถามนี้ตั้งแต่แรก ขอขอบคุณ.
NPS

12

(ในระบบของฉันไม่ได้ทดสอบที่อื่น) ใน GL การใส่ตาข่ายเดียว (การวาดด้วย count = 1) มีค่าใช้จ่ายที่น่ารังเกียจบ้าง แต่ฉันไม่รู้ว่ามาจากไหน ฉันขอแนะนำไม่ให้ทำ

ฉันทดสอบสิ่งนี้ในแอปพลิเคชั่นที่ใช้งานได้จริงเมื่อสองสามเดือนที่ผ่านมา ฉันเขียนอัลกอริธึมการส่องสว่างระดับโลกบางส่วนในฉาก Crytek Sponza ซึ่งประกอบด้วยตาข่ายประมาณ 350 หรือมากกว่านั้น (จำไม่ได้แน่นอน) ซึ่งคู่รักสองคนแบ่งปันอินสแตนซ์จำนวนหนึ่ง ในตอนแรกฉันทำตามที่คุณแนะนำเพียงแค่ทุกอย่างและดึงส่วนที่เหลือด้วยจำนวนอินสแตนซ์ 1 เนื่องจากมันทำให้การเรนเดอร์โค้ดง่ายขึ้นเล็กน้อย

ต่อมาเมื่อปรับแต่งโหมดเรนเดอร์เพียงแค่สลับกลับจากการใส่วัตถุ count = 1 เพื่อส่งพวกเขาด้วยวิธีปกติช่วยฉันประมาณ3.5 มิลลิวินาทีต่อหนึ่งเฟรมที่คุ้มค่ากับเวลาใน i7 3770k (และ GTX 770) การสลับตาข่ายด้วยหลายอินสแตนซ์เป็นการทำแบบดั้งเดิมช่วยฉันอีก 0.5ms โดยรวมแล้วแอปพลิเคชันเปลี่ยนจาก ~ 120 FPS เป็นประมาณ ~ 230 FPS

แน่นอนว่าตัวเลขเหล่านี้ขึ้นอยู่กับว่าคอขวดอยู่ในแอปพลิเคชั่นของคุณหรือไม่และ 0.5 มิลลิวินาทีหลังอาจช้าลงในแอปพลิเคชันที่คุณถูก จำกัด การโทรเสมอ แต่อย่างอื่นในประสบการณ์ของฉัน instancing มีค่าใช้จ่ายที่น่ารังเกียจบางอย่างถ้าคุณไม่ได้วาดสิ่งต่าง ๆ มากมายในครั้งเดียว


น่าสนใจ แต่มันก็ดีที่ได้เห็นข้อมูลสำหรับไดรเวอร์ AMD และ Intel เช่นกันคุณควรพูดว่า "ในระบบของฉัน" แทนที่จะเป็น "In GL" ในทางตรงกันข้ามแม้ว่ามันจะไม่เป็นปัญหากับการใช้งานอื่น ๆ ความจริงที่ว่ามันอาจจะมีบางเหตุผลเพียงพอที่จะหลีกเลี่ยงการติดตั้งถ้าคุณไม่ได้ใช้งาน
bcrist

2

คุณสามารถมั่นใจได้ว่าการวาดวัตถุเดียวที่มีความซับซ้อนนั้นมีราคาแพงกว่าการวาดวัตถุเดียวตามปกติ สำหรับการติดตั้ง GPU กำลังเตรียมสำหรับวัตถุจำนวนมากและการเตรียมการนี้จะแตกต่างจากวัตถุเดี่ยว อย่างไรก็ตามช่องว่างประสิทธิภาพนี้มีขนาดใหญ่เพียงใดโดยการทดลองและขึ้นอยู่กับการตั้งค่าการแสดงผลจริงของคุณ วิธีเดียวที่จะรู้แน่นอนคือการทดสอบด้วยตัวเอง การเปรียบเทียบการจับฉลากครั้งเดียวทำได้ยากที่นี่มีหลายแนวคิดเกี่ยวกับวิธีการดำเนินการต่อ


2

4 ปีแล้ว ... และฉันคิดว่ามันปลอดภัยที่จะพูดได้ว่าสมบูรณ์แบบในการส่งการโทร "instanced" กับ 1 เนื่องจากคุณอาจสังเกตเห็น APIs DX12และVk ใหม่ทั้งคู่มีอินสแตนซ์นับจาก 0 ถึงNUM_INSTANCES นอกจากนี้ยังทราบว่าไม่มีDrawIndexed ( ... )

แก้ไข

ข้อควรระวังข้างต้นอาจใช้ได้กับ API ที่ทันสมัยนี้อาจใช้สิ่งเก่าเช่น Gl <3.3 หรือ DX11 อาจจะต้องมีการทำโปรไฟล์ตามที่ผู้ใช้รายอื่นกล่าวถึง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.