วิเคราะห์รูปแบบจุดยอด

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

มุมมองการทำโปรไฟล์เฟรมสำหรับการเรียก glDrawElements ที่วางเมาส์เพื่อดูรายละเอียด
            ในพารามิเตอร์การเรียกวาด
รูปที่ 1 มุมมองการสร้างโปรไฟล์เฟรมสำหรับ glDrawElementsการเรียกใช้ครั้งเดียว ซึ่งแสดงรูปสามเหลี่ยม 2,718 รูปที่วาด

การบีบอัดแอตทริบิวต์ของจุดยอด

ปัญหาที่พบบ่อยอย่างหนึ่งที่เกมของคุณอาจเจอคือขนาดจุดยอดเฉลี่ยที่ใหญ่ การส่งจุดยอดจำนวนมากที่มีขนาดจุดยอดเฉลี่ยสูงจะส่งผลให้แบนด์วิดท์การอ่านหน่วยความจำจุดยอดมีขนาดใหญ่เมื่อ GPU อ่าน

หากต้องการสังเกตรูปแบบจุดยอดสำหรับการเรียกใช้การวาดที่เฉพาะเจาะจง ให้ทำตามขั้นตอนต่อไปนี้

  1. เลือกการเรียกใช้การวาดที่ต้องการ

    ซึ่งอาจเป็น Draw Call ทั่วไปสำหรับฉาก, Draw Call ที่มีจุดยอดจำนวนมาก, Draw Call สำหรับโมเดลตัวละครที่ซับซ้อน หรือ Draw Call ประเภทอื่นๆ

  2. ไปที่แผงไปป์ไลน์ แล้วคลิก IA สำหรับการประกอบอินพุต ซึ่งจะกำหนดรูปแบบจุดยอดสำหรับจุดยอดที่เข้ามาใน GPU

  3. สังเกตแอตทริบิวต์และรูปแบบของแอตทริบิวต์ชุดหนึ่ง เช่น R32G32B32_SFLOAT คือโฟลตแบบมีเครื่องหมาย 32 บิตที่มี 3 องค์ประกอบ

มุมมองการทำโปรไฟล์เฟรมสำหรับการประกอบอินพุตของ Draw Call โดยมี
            แอตทริบิวต์ของจุดยอดที่ไม่ได้บีบอัด
รูปที่ 2 การประกอบอินพุตสำหรับการเรียกวาด โดยมีแอตทริบิวต์ที่ไม่ได้บีบอัด ซึ่งส่งผลให้ขนาดของจุดยอดเป็น 56 ไบต์

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

  • การบีบอัดตำแหน่งจุดยอดเป็นจำนวนทศนิยมแบบ 16 บิตที่มีความแม่นยำครึ่งหนึ่ง
  • การบีบอัดพิกัดพื้นผิว UV เป็นจำนวนเต็มแบบไม่มีเครื่องหมาย 16 บิต
  • การบีบอัดพื้นที่แทนเจนต์โดยการเข้ารหัสเวกเตอร์ปกติ แทนเจนต์ และไบแทนเจนต์ โดยใช้ควอเทอร์เนียน

นอกจากนี้ ระบบอาจพิจารณาแอตทริบิวต์อื่นๆ ที่เกี่ยวข้องสำหรับประเภทที่มีความแม่นยำต่ำกว่า เป็นกรณีๆ ไป

การแยกสตรีมของ Vertex

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

หากต้องการลดแบนด์วิดท์ของหน่วยความจำที่อ่าน Vertex และปรับปรุงประสิทธิภาพแคช รวมถึง ลดเวลาที่ใช้ในการส่งผ่านการจัดกลุ่ม ควรแยกข้อมูล Vertex ออกเป็น 2 สตรีม แยกกัน สตรีมหนึ่งสำหรับตำแหน่ง Vertex และอีกสตรีมหนึ่งสำหรับแอตทริบิวต์ Vertex อื่นๆ ทั้งหมด

วิธีตรวจสอบว่าแอตทริบิวต์เวอร์เท็กซ์แยกอย่างเหมาะสมหรือไม่

  1. เลือกการเรียกใช้การวาดที่สนใจ แล้วจดหมายเลขการเรียกใช้การวาด

    ซึ่งอาจเป็น Draw Call ทั่วไปสำหรับฉาก, Draw Call ที่มีจุดยอดจำนวนมาก, Draw Call สำหรับโมเดลตัวละครที่ซับซ้อน หรือ Draw Call ประเภทอื่นๆ

  2. ไปที่แผงไปป์ไลน์ แล้วคลิก IA สำหรับการประกอบอินพุต ซึ่ง กำหนดรูปแบบจุดยอดสำหรับจุดยอดที่เข้ามาใน GPU

  3. สังเกตการเชื่อมโยงแอตทริบิวต์จุดยอด โดยปกติแล้วการเชื่อมโยงเหล่านี้อาจ เพิ่มขึ้นเป็นเส้นตรง (0, 1, 2, 3 ฯลฯ) แต่ก็ไม่ได้เป็นเช่นนี้เสมอไป โดยปกติแล้วตำแหน่งจุดยอดจะเป็นแอตทริบิวต์จุดยอดแรกที่แสดง

  4. ในแผงสถานะ ให้ค้นหา LastDrawInfos แล้วขยายหมายเลขการเรียก ที่ตรงกัน จากนั้นขยาย BoundVertexBuffers สำหรับการเรียกใช้การวาดนี้

  5. สังเกตบัฟเฟอร์จุดยอดที่เชื่อมโยงระหว่างการเรียกวาดที่ระบุ โดยมีดัชนี ที่ตรงกับการเชื่อมโยงแอตทริบิวต์จุดยอดจากก่อนหน้านี้

  6. ขยายการเชื่อมโยงสำหรับแอตทริบิวต์จุดยอดของการเรียกวาด และขยายบัฟเฟอร์

  7. สังเกต VulkanHandle สำหรับบัฟเฟอร์ ซึ่งแสดงถึงหน่วยความจำพื้นฐานที่แหล่งข้อมูลจุดยอดมาจาก หาก VulkanHandle แตกต่างกัน แสดงว่าแอตทริบิวต์มาจากบัฟเฟอร์พื้นฐานที่แตกต่างกัน หาก VulkanHandle เหมือนกัน แต่มีการออฟเซ็ตขนาดใหญ่ (เช่น มากกว่า 100) แอตทริบิวต์อาจยังคงมาจาก บัฟเฟอร์ย่อยที่แตกต่างกัน แต่ต้องมีการตรวจสอบเพิ่มเติม

มุมมองการจัดโปรไฟล์เฟรมสำหรับการประกอบอินพุตและการเรียกใช้สถานะการวาดที่แสดงบัฟเฟอร์จุดยอดที่เชื่อมโยง
รูปที่ 3 การประกอบอินพุตสำหรับการเรียกวาด โดยมีแผงสถานะทางด้านขวาแสดงว่าแอตทริบิวต์ที่การเชื่อมโยง 0 และ 1, ตำแหน่งจุดยอด และค่าปกติใช้บัฟเฟอร์พื้นฐานเดียวกัน

ดูรายละเอียดเพิ่มเติมเกี่ยวกับการแยกสตรีมของ Vertex และวิธีแก้ไขในเกมเอนจินต่างๆ ได้ในบล็อกโพสต์ของเราในหัวข้อนี้