การเพิ่มประสิทธิภาพ Vulkan ของ Godot Engine สำหรับ Android

รูปภาพมาสคอตของ Godot Engine

ภาพรวม

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

มูลนิธิ Godot ได้ว่าจ้างผู้เชี่ยวชาญด้านการเพิ่มประสิทธิภาพกราฟิกที่ The Forge Interactive และทำงานร่วมกับ Google เพื่อวิเคราะห์และปรับปรุงโปรแกรมแสดงผล Vulkan ของ Godot 4 ให้ดียิ่งขึ้น รวมถึงผสานการเพิ่มประสิทธิภาพเหล่านั้นกลับไปยังที่เก็บโปรเจ็กต์ การเพิ่มประสิทธิภาพนี้ช่วยให้นักพัฒนาแอปปรับปรุงโปรแกรมแสดงผล Vulkan แบบกำหนดเองบน Android ได้

วิธีการและผลลัพธ์การเพิ่มประสิทธิภาพ

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

มีการทดสอบสถาปัตยกรรม GPU ยอดนิยมหลายรายการของ Android แม้ว่าการเพิ่มประสิทธิภาพหลายรายการจะนำมาซึ่งการปรับปรุงทั่วไป แต่การเพิ่มประสิทธิภาพบางอย่างก็ส่งผลต่อสถาปัตยกรรม GPU บางรายการมากกว่า ผลรวมของงานการเพิ่มประสิทธิภาพทั้งหมดส่งผลให้เวลาเฟรมของ GPU ลดลง 10-20% โดยเฉลี่ย

การเพิ่มประสิทธิภาพ Vulkan ทั่วไป

Forge ทำการรีแฟกทอริงสถาปัตยกรรมทั่วไปในแบ็กเอนด์การแสดงผลของ Godot Vulkan เพื่อปรับปรุงประสิทธิภาพและช่วยให้แบ็กเอนด์ปรับขนาดตามดีมานด์การแสดงผลเนื้อหาที่เพิ่มขึ้น การเพิ่มประสิทธิภาพนี้ไม่ได้มุ่งเน้นที่ฮาร์ดแวร์ของอุปกรณ์เคลื่อนที่โดยเฉพาะ แต่ให้ประโยชน์กับแพลตฟอร์ม Godot Vulkan ทั้งหมด

การรองรับออฟเซต UBO แบบไดนามิก

เมื่อเชื่อมโยงชุดตัวระบุที่มีออบเจ็กต์บัฟเฟอร์แบบคงที่แบบไดนามิก (UBO) Vulkan อนุญาตให้ระบุออฟเซตแบบไดนามิกใน UBO ในพารามิเตอร์การเชื่อมโยง ฟีเจอร์นี้สามารถใช้เพื่อแพ็กข้อมูลสําหรับการดําเนินการการเรนเดอร์หลายรายการไว้ใน UBO รายการเดียว ผูกชุดตัวระบุอีกครั้งด้วยออฟเซตแบบไดนามิกอื่นเพื่อเลือกข้อมูลที่ถูกต้องสําหรับโปรแกรมเปลี่ยนรูปแบบ โปรแกรมแสดงผล Vulkan ของ Godot ได้รับการอัปเดตให้ใช้การเลื่อนเชิงรัศมีแบบไดนามิกแทนการเริ่มต้นการเลื่อนเป็น 0 เสมอ การปรับปรุงนี้ช่วยให้สามารถเพิ่มประสิทธิภาพในอนาคต

พูลชุดตัวระบุเชิงเส้น

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

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

การรองรับเครื่องมือวัดผลแบบคงที่

ออบเจ็กต์ Sampler ที่มีข้อมูลการกําหนดค่าการสุ่มตัวอย่างมักจะเชื่อมโยงเป็นส่วนหนึ่งของข้อมูลชุดตัวระบุ วิธีนี้ช่วยให้สามารถสลับออบเจ็กต์ตัวอย่างออกได้แบบไดนามิกในข้อมูลชุดตัวระบุ นอกจากนี้ Vulkan ยังรองรับตัวอย่างที่ไม่เปลี่ยนแปลง ซึ่งจะเข้ารหัสข้อมูลตัวอย่างลงในเลย์เอาต์ชุดตัวบ่งชี้โดยตรง การกําหนดค่าเครื่องมือสุ่มตัวอย่างนี้จะเชื่อมโยงเมื่อสร้างชุดตัวบ่งชี้และสถานะไปป์ไลน์ และไม่สามารถเปลี่ยนแปลงได้หลังจากสร้าง

Sampler แบบคงที่จะแลกความยืดหยุ่นเพื่อไม่ต้องจัดการและเชื่อมโยงออบเจ็กต์ Sampler แบบแยกต่างหากอีกต่อไป โปรแกรมแสดงผล Vulkan ของ Godot ได้รับการอัปเดตให้รองรับการใช้ Sampler แบบคงที่ และเปลี่ยนการใช้งาน Sampler ให้ใช้ Sampler แบบคงที่ตามความเหมาะสม

การเพิ่มประสิทธิภาพที่มุ่งเน้นอุปกรณ์เคลื่อนที่

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

การเพิ่มประสิทธิภาพ ได้แก่

  • แทนที่การใช้ค่าคงที่ Push ขนาดใหญ่
  • การจัดสรรบัฟเฟอร์แบบ Lazy
  • การรองรับบัฟเฟอร์ถาวร
  • การเปลี่ยนแปลงโหมดการถอดรหัส ASTC
  • การหมุนหน้าจอก่อนการล็อก

แทนที่การใช้ค่าคงที่ Push ขนาดใหญ่

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

ในระหว่างการทดสอบในอุปกรณ์ Android ประสิทธิภาพได้รับการปรับปรุงโดยการแทนที่การใช้ Push แบบคงที่มากกว่า 16 ไบต์ด้วยบัฟเฟอร์แบบรวม Shader ที่ใช้ข้อมูลคงที่ไม่เกิน 16 ไบต์มีประสิทธิภาพมากขึ้นเมื่อใช้ Push Constant นอกจากการพิจารณาด้านประสิทธิภาพแล้ว ฮาร์ดแวร์กราฟิกบางรุ่นยังมีการจัดแนวขั้นต่ำ 64 ไบต์สำหรับบัฟเฟอร์แบบเดียวกัน ซึ่งจะลดประสิทธิภาพหน่วยความจำเนื่องจากมีการเพิ่มค่าที่ไม่ได้ใช้เมื่อเทียบกับการใช้ค่าคงที่แบบ Push

การจัดสรรบัฟเฟอร์แบบ Lazy

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

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

การรองรับบัฟเฟอร์ถาวร

ฮาร์ดแวร์ของอุปกรณ์เคลื่อนที่ใช้สถาปัตยกรรมหน่วยความจำแบบรวม (UMA) แทนการแยกฮาร์ดแวร์ระหว่าง RAM หลักกับ RAM กราฟิก เมื่อ RAM หลักและ RAM กราฟิกแยกกัน ข้อมูลจะต้องโอนจาก RAM หลักไปยัง RAM กราฟิกเพื่อให้ GPU ใช้ Godot ใช้กระบวนการโอนนี้ในโปรแกรมแสดงผล Vulkan อยู่แล้วผ่านการใช้บัฟเฟอร์การจัดเก็บข้อมูลชั่วคราว ในฮาร์ดแวร์ UMA บัฟเฟอร์การจัดเก็บข้อมูลชั่วคราวไม่จำเป็นสำหรับข้อมูลหลายประเภท เนื่องจากทั้ง CPU และ GPU สามารถใช้หน่วยความจำได้ Forge รองรับบัฟเฟอร์ที่แชร์แบบถาวรในฮาร์ดแวร์ที่รองรับเพื่อลดการจัดเตรียมเมื่อเป็นไปได้

รูปภาพของฉาก godot ที่แสดงข้อมูลการโปรไฟล์ทั้งที่มีและไม่มีการเปิดใช้บัฟเฟอร์ถาวร
รูปที่ 1 การสร้างโปรไฟล์ความแตกต่างระหว่างบัฟเฟอร์ถาวรที่เปิดและปิดใช้ในฉากตัวอย่าง

การเปลี่ยนแปลงโหมดการถอดรหัส ASTC

การบีบอัดพื้นผิวแบบปรับขนาดได้ (ASTC) เป็นรูปแบบการบีบอัดพื้นผิวสมัยใหม่ที่ต้องการในฮาร์ดแวร์อุปกรณ์เคลื่อนที่ ในระหว่างการขยายไฟล์ GPU อาจถอดรหัสเท็กเซลเป็นค่ากลางที่มีความแม่นยำมากกว่าที่จำเป็นสำหรับภาพให้สมจริงโดยค่าเริ่มต้น ซึ่งจะทำให้ประสิทธิภาพของพื้นผิวลดลง หากฮาร์ดแวร์เป้าหมายรองรับ ระบบจะใช้ส่วนขยาย VK_EXT_astc_decode_mode เพื่อระบุค่า 8 บิตที่ไม่ได้ทำให้เป็นมาตรฐานต่อองค์ประกอบเมื่อถอดรหัสแทนค่าทศนิยม 16 บิต

การหมุนหน้าจอก่อนการล็อก

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

การปรับปรุงการแก้ไขข้อบกพร่อง

นอกจากการเพิ่มประสิทธิภาพแล้ว The Forge ยังปรับปรุงประสบการณ์การแก้ไขข้อบกพร่องเกี่ยวกับกราฟิกในโปรแกรมแสดงผล Godot ด้วยการเพิ่มฟีเจอร์ต่อไปนี้

  • การขยายเวลาในการแจ้งข้อบกพร่องของอุปกรณ์
  • การแสดงเส้นทาง
  • เครื่องหมายการแก้ไขข้อบกพร่อง

การขยายเวลาเนื่องจากข้อบกพร่องของอุปกรณ์

เมื่อ GPU พบปัญหาระหว่างการดำเนินการแสดงผล โปรแกรมควบคุม Vulkan จะแสดงผลลัพธ์ VK_ERROR_DEVICE_LOST จากการเรียกใช้ Vulkan API ได้ โดยค่าเริ่มต้น ระบบจะไม่ระบุข้อมูลเพิ่มเติมเกี่ยวกับบริบทว่าเหตุใดไดรเวอร์จึงแสดงVK_ERROR_DEVICE_LOST ส่วนขยาย VK_EXT_device_fault มีกลไกให้ไดรเวอร์ระบุข้อมูลเพิ่มเติมเกี่ยวกับลักษณะของข้อบกพร่อง Godot เพิ่มการรองรับการเปิดใช้ส่วนขยายข้อบกพร่องของอุปกรณ์ (หากมี) และการรายงานข้อมูลที่ได้จากไดรเวอร์

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

เครื่องหมายการแก้ไขข้อบกพร่อง

ระบบจะใช้เครื่องหมายแก้ไขข้อบกพร่อง (หากโปรแกรมควบคุมรองรับ) เพื่อตั้งชื่อทรัพยากร ซึ่งช่วยให้เชื่อมโยงสตริงที่ผู้ใช้อ่านได้กับการดำเนินการต่างๆ เช่น ผ่านการแสดงผล และทรัพยากร เช่น บัฟเฟอร์และพื้นผิว เมื่อใช้เครื่องมือกราฟิก เช่น RenderDoc เพิ่มการรองรับคำอธิบายประกอบเครื่องหมายแก้ไขข้อบกพร่องลงในโปรแกรมแสดงผล Vulkan ของ Godot

บล็อก Godot Engine - ข้อมูลอัปเดตเกี่ยวกับการทํางานร่วมกันกับ Google และ The Forge

คำขอดึงข้อมูลการทำงานร่วมกันใน Vulkan ของ Godot Engine