วิธีแคชทรัพยากรในระบบการแสดงผล homebrew ของฉัน


10

พื้นหลัง:

ฉันกำลังออกแบบระบบการเรนเดอร์ 3D แบบง่ายสำหรับสถาปัตยกรรมชนิดเอนทิตีคอมโพเนนต์โดยใช้ C ++ และ OpenGL ระบบประกอบด้วย renderer และกราฟฉาก เมื่อฉันเสร็จสิ้นการทำซ้ำครั้งแรกของโหมดแสดงภาพฉันอาจกระจายกราฟฉากลงในสถาปัตยกรรม ECS สำหรับตอนนี้มันเป็นตัวยึดตำแหน่งทางเดียวหรืออื่น หากเป็นไปได้ต่อไปนี้เป็นเป้าหมายของฉันสำหรับผู้สร้างภาพ:

  1. ความง่าย นี่เป็นโครงการวิจัยและฉันต้องการที่จะสามารถเปลี่ยนแปลงและขยายระบบของฉันได้อย่างง่ายดาย (ด้วยวิธีการของ ECS)
  2. การปฏิบัติ ฉากของฉันอาจมีนางแบบขนาดเล็กจำนวนมากและยังมีเล่มขนาดใหญ่ที่มีรูปทรงเรขาคณิตมากมาย ไม่สามารถรับวัตถุจากบริบท OGL และเรขาคณิตบัฟเฟอร์ทุกเฟรมการเรนเดอร์ ฉันตั้งเป้าหมายในการหาที่ตั้งของข้อมูลเพื่อหลีกเลี่ยงการพลาดแคช
  3. มีความยืดหยุ่น มันจะต้องสามารถแสดงสไปรต์โมเดลและโวลุ่ม (voxels)
  4. แยกออก กราฟฉากอาจถูก refactored ลงในสถาปัตยกรรมหลักของ ECS หลังจากที่ฉันเขียน renderer ของฉัน
  5. modular เป็นเรื่องดีที่สามารถสลับในโหมดแสดงภาพที่ต่างกันได้โดยไม่ต้องเปลี่ยนกราฟฉากของฉัน
  6. ความโปร่งใสอ้างอิงซึ่งหมายความว่า ณ เวลาใด ๆ ฉันสามารถให้มันถูกต้องฉากใด ๆ และมันจะทำให้ภาพเดียวกันสำหรับฉากนั้น โดยเฉพาะอย่างยิ่งเป้าหมายนี้ไม่จำเป็นต้องมี ฉันคิดว่ามันจะช่วยทำให้การจัดลำดับฉากเป็นเรื่องง่ายขึ้น (ฉันจะต้องสามารถบันทึกและโหลดฉาก) และให้ความยืดหยุ่นในการสลับฉากต่าง ๆ ระหว่างรันไทม์เพื่อการทดสอบ / การทดลอง

ปัญหาและแนวคิด:

ฉันได้ลองวิธีที่แตกต่างกัน แต่ฉันพยายามดิ้นรนกับวิธีการแคชทรัพยากร OGL (VAO, VBOs, shaders ฯลฯ ) สำหรับโหนดการแสดงผลแต่ละโหนด ต่อไปนี้เป็นแนวคิดการแคชที่แตกต่างกันที่ฉันคิดไว้จนถึงตอนนี้:

  1. แคชส่วนกลาง. แต่ละโหนดของฉากมี ID และตัวแสดงภาพมีแคชที่จับคู่รหัสเพื่อแสดงผลโหนด โหนดการแสดงผลแต่ละโหนดมี VAO และ VBO ที่เกี่ยวข้องกับรูปทรงเรขาคณิต แคชมิสได้มาซึ่งทรัพยากรและแมปเรขาคณิตกับโหนดการแสดงผลในแคช เมื่อรูปทรงเรขาคณิตมีการเปลี่ยนแปลงการตั้งค่าสถานะสกปรก หากตัวแสดงภาพเห็นธงรูปทรงเรขาคณิตสกปรกในขณะที่วนดูผ่านโหนดของฉากก็จะทำการรีบูตข้อมูลโดยใช้โหมดการแสดงผล เมื่อโหนดฉากถูกลบออกเหตุการณ์จะถูกออกอากาศและ renderer จะลบโหนดการแสดงผลที่เกี่ยวข้องออกจากแคชในขณะที่ปล่อยทรัพยากร หรือมิฉะนั้นโหนดจะถูกทำเครื่องหมายสำหรับการลบและ renderer รับผิดชอบในการลบออก ฉันคิดว่าวิธีการนี้บรรลุเป้าหมาย 6 อย่างใกล้ชิดที่สุดในขณะที่การพิจารณา 4 และ 5 2 ประสบกับความซับซ้อนและการสูญเสียข้อมูลในพื้นที่ด้วยการค้นหาแผนที่แทนการเข้าถึงอาร์เรย์
  2. แคชกระจาย คล้ายกันด้านบนยกเว้นแต่ละโหนดของฉากมีโหนดการแสดงผล การทำเช่นนี้จะข้ามการค้นหาแผนที่ เพื่อระบุตำแหน่งของข้อมูล data โหนดการเรนเดอร์สามารถเก็บไว้ใน renderer จากนั้นโหนดของฉากอาจมีพอยน์เตอร์แทนการเรนเดอร์แทนและ renderer จะตั้งค่าตัวชี้บนแคชมิส ฉันคิดว่าการเลียนแบบวิธีนี้เป็นองค์ประกอบเอนทิตีดังนั้นมันจะสอดคล้องกับส่วนที่เหลือของสถาปัตยกรรม ปัญหาคือตอนนี้โหนดของซีนจัดเก็บข้อมูลเฉพาะ renderer-implementation ถ้าฉันเปลี่ยนวิธีการแสดงผลสิ่งต่าง ๆ ในโหมดแสดงภาพ (เช่นเรนเดอร์เรนเดอร์ vs ปริมาตร) ตอนนี้ฉันต้องเปลี่ยนโหมดการแสดงผลหรือเพิ่ม "องค์ประกอบ" ไปยังโหนดภาพ (ซึ่งหมายถึงการเปลี่ยนกราฟฉากด้วย) ในด้านบวกนี่เป็นวิธีที่ง่ายที่สุดในการทำให้ตัวเรนเดอร์ตัวแรกของฉันทำงาน
  3. เมตาดาต้ากระจาย คอมโพเนนต์ข้อมูลเมตาแคช renderer ถูกเก็บไว้ในแต่ละโหนดของฉาก ข้อมูลนี้ไม่ได้เจาะจงใช้งาน แต่เก็บ ID ประเภทและข้อมูลอื่น ๆ ที่เกี่ยวข้องที่แคชต้องการ จากนั้นการค้นหาแคชสามารถทำได้โดยตรงในอาร์เรย์โดยใช้ ID และประเภทสามารถระบุประเภทของวิธีการแสดงผลที่จะใช้ (เช่นสไปรต์และปริมาณ)
  4. จำนวนผู้เข้าชม + กระจายการทำแผนที่ โหมดแสดงภาพเป็นโหนดผู้เข้าชมและโหนดเป็นองค์ประกอบในรูปแบบผู้เยี่ยมชม แต่ละโหนดของฉากถือคีย์แคช (เช่นข้อมูลเมตา แต่เป็น ID) ที่มีเฉพาะเรนเดอร์เท่านั้น ID สามารถใช้สำหรับอาร์เรย์แทนการค้นหาแผนที่ทั่วไป โหมดแสดงภาพสามารถอนุญาตให้โหนดซีนเพื่อจัดส่งฟังก์ชั่นการแสดงผลที่แตกต่างกันตามชนิดของโหนดฉากและ ID สามารถใช้โดยแคชใด ๆ รหัสเริ่มต้นหรืออยู่นอกช่วงจะระบุว่าแคชไม่ได้

คุณจะแก้ปัญหานี้อย่างไร หรือคุณมีข้อเสนอแนะใด ๆ ขอบคุณที่อ่านกำแพงข้อความของฉัน!


1
คุณมีความคืบหน้าใด ๆ
Andreas

นี่เป็นคำถามที่ซับซ้อนมากและน่าจะถูกแบ่งออกเป็นหลายคำถาม นี่คือคำถามที่ถามว่า "ฉันควรออกแบบเครื่องยนต์อย่างไร" คำแนะนำของฉันคือการออกแบบสิ่งที่สนับสนุนส่วนประกอบที่ง่ายกว่าก่อนจากนั้นจึงเพิ่มและปรับคุณสมบัติตามที่คุณต้องการ ค้นหาหนังสือออกแบบเครื่องมือเกม 3D ซึ่งควรครอบคลุมข้อมูลจำนวนมากที่คุณกำลังมองหา
Ian Young

คำตอบ:


2

หลังจากอ่านคำถามของคุณอีกครั้งฉันรู้สึกว่าคุณกำลังเข้าใจปัญหาอย่างมาก นี่คือเหตุผล:

  1. ระบบการเรนเดอร์มีเพียงสองประเภทเท่านั้น: การส่งต่อและการเลื่อนเวลาซึ่งไม่มีการพึ่งพากราฟฉาก

  2. ปัญหาด้านประสิทธิภาพเพียงอย่างเดียวที่คุณควรได้รับจากระบบการแสดงผลใด ๆ ควรมาจากจำนวนโพลีที่สูงและส่วนที่ไม่มีประสิทธิภาพและรหัสลูกค้า

  3. Cache คิดถึงจะลดประสิทธิภาพลงอย่างแน่นอน แต่พวกมันไม่ใช่สัตว์ประหลาดที่คุณคิดว่าเป็น 80% ของการปรับปรุงประสิทธิภาพของคุณจะมาจากอัลกอริทึมที่มีประสิทธิภาพมากขึ้น อย่าทำผิดพลาดในการเพิ่มประสิทธิภาพรหัสของคุณล่วงหน้า

ที่กล่าวว่า:

หากคุณใช้ Homebrew Scenegraph คุณควรใช้อินเทอร์เฟซ "Renderer" (หรือคลาสพื้นฐาน) เพื่อออกแบบส่วนการเรนเดอร์ของโค้ด Scenegraph ของคุณ รูปแบบของผู้เข้าชมที่ใช้การแจกจ่ายสองครั้งเป็นวิธีการที่ดีในการนี้เนื่องจากคุณอาจใช้โหนดกราฟหลายชนิดเช่นสีพื้นผิวตาข่ายการแปลง ฯลฯ ด้วยวิธีนี้ในระหว่างรอบการเรนเดอร์เรนเดอร์ทั้งหมดต้องทำคือ เดินโครงสร้างต้นไม้ฉากที่ลึกที่สุดก่อนผ่านตัวมันเองเป็นอาร์กิวเมนต์ ด้วยวิธีนี้ตัวเรนเดอร์เป็นเพียงชุดของเงาและอาจเป็นเฟรมบัฟเฟอร์หรือสองอัน ผลลัพธ์ของสิ่งนี้คือรหัสการค้นหา / การลบไม่จำเป็นสำหรับระบบการแสดงผลอีกต่อไป

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

จากนั้นคุณจะถูกวางไว้อย่างดีในการตัดสินใจอย่างชาญฉลาด

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