ไลบรารีการกำหนดอัตราการแสดงโฆษณาเฟรม เป็นส่วนหนึ่งของชุดเครื่องมือพัฒนาเกม Android
ไลบรารี Android Frame Pacing หรือที่รู้จักกันในชื่อ Swappy เป็นส่วนหนึ่งของไลบรารี AGDK ช่วยให้เกม OpenGL และ Vulkan แสดงผลอย่างลื่นไหลและ ความเร็วของเฟรมใน Android ถูกต้อง เอกสารนี้จะระบุอัตราของเฟรม ซึ่งอธิบาย สถานการณ์ที่จำเป็นต้องใช้อัตราเฟรมเฟรม และแสดงให้เห็นว่าที่อยู่ไลบรารี เหล่านี้ หากคุณต้องการเปลี่ยนไปใช้การใช้การกำหนดอัตราการแสดงโฆษณาเฟรมโดยตรงใน เกมของคุณ โปรดดูขั้นตอนถัดไป
ฉากหลัง
การกำหนดอัตราการแสดงโฆษณาเฟรมคือการซิงค์ตรรกะของเกมและลูปการแสดงผลกับ ระบบย่อยของจอแสดงผลระบบปฏิบัติการและฮาร์ดแวร์การแสดงผลที่ใช้ Android ระบบย่อยของจอแสดงผลออกแบบมาเพื่อหลีกเลี่ยงสิ่งแปลกปลอมทางภาพ (หรือที่เรียกว่าการฉีกขาด) จะเกิดขึ้นเมื่อฮาร์ดแวร์แสดงผลเปลี่ยนไปเป็นเฟรมใหม่บางส่วน ผ่านการอัปเดต เพื่อหลีกเลี่ยงอาร์ติแฟกต์เหล่านี้ ระบบย่อยของจอแสดงผลจะดำเนินการ ดังต่อไปนี้:
- บัฟเฟอร์ที่ผ่านเฟรมภายใน
- ตรวจหาการส่งเฟรมล่าช้า
- แสดงเฟรมที่ผ่านมาซ้ำเมื่อตรวจพบเฟรมที่ล่าช้า
เกมแจ้ง
SurfaceFlinger
คอมโพสิเตอร์ภายในระบบย่อยของจอแสดงผล
ว่าได้ส่งคำขอแสดงผลทั้งหมด
จำนวนการโทรที่จำเป็นสำหรับเฟรม (โดยเรียกใช้ eglSwapBuffers
หรือ vkQueuePresentKHR
)
SurfaceFlinger ส่งสัญญาณความพร้อมใช้งานของเฟรมไปยังฮาร์ดแวร์จอแสดงผลโดยใช้
สลัก จากนั้นฮาร์ดแวร์จอแสดงผลจะแสดงเฟรมที่กำหนด ฮาร์ดแวร์แสดงผล
ที่อัตราคงที่ เช่น 60 Hz และหากไม่มีเฟรมใหม่
หากฮาร์ดแวร์ต้องการเฟรม ฮาร์ดแวร์จะแสดงเฟรมก่อนหน้าอีกครั้ง
เวลาที่ใช้ในการแสดงผลเฟรมที่ไม่สอดคล้องกันมักเกิดขึ้นเมื่อการแสดงผลเกมวนซ้ำ อัตราแตกต่างจาก ฮาร์ดแวร์จอแสดงผลในเครื่อง หากเกมที่ทำงานที่ 30 FPS พยายามแสดงผลบนอุปกรณ์ที่รองรับ 60 FPS ตั้งแต่ต้น ซึ่งเป็นการแสดงผลเกม การวนซ้ำไม่ตระหนักว่ามีเฟรมซ้ำอยู่บนหน้าจอเป็นเวลาเพิ่มอีก 16 มิลลิวินาที การตัดการเชื่อมต่อนี้มักจะทำให้เกิดความไม่สอดคล้องกันอย่างมากในเฟรม เช่น 49 มิลลิวินาที, 16 มิลลิวินาที, 33 มิลลิวินาที มากเกินไป ฉากที่ซับซ้อนจะยิ่งผสานปัญหานี้ลงไปอีก เพราะจะทำให้เฟรมพลาดไป เกิดขึ้น
โซลูชันที่ไม่ได้เหมาะสมที่สุด
เกมต่างๆ เคยใช้โซลูชันสำหรับการกำหนดจังหวะเฟรมต่อไปนี้ และมักทำให้เวลาที่ใช้ในการแสดงผลเฟรมไม่สม่ำเสมอและเพิ่มเวลาในการตอบสนองของอินพุต
ส่งเฟรมโดยเร็วที่สุดเท่าที่ API การแสดงผลอนุญาต
แนวทางนี้จะเชื่อมโยงเกมกับกิจกรรม SurfaceFlinger ที่มีตัวแปรและเปิดตัว เฟรมเวลาในการตอบสนองเพิ่มเติม ไปป์ไลน์การแสดงผลจะมีคิวของเฟรม โดยปกติจะมีขนาดอยู่ที่ 2 ซึ่งจะเติมเต็มหากเกมพยายามนำเสนอเฟรมด้วย อย่างรวดเร็ว ไม่มีที่ว่างในคิว เกมลูป (หรืออย่างน้อยก็ เทรดการแสดงผล) ถูกบล็อกโดยการเรียกใช้ OpenGL หรือ Vulkan เกมเริ่มแล้ว บังคับให้รอฮาร์ดแวร์จอแสดงผลเพื่อแสดงเฟรม และการกดย้อนกลับนี้ จะซิงค์องค์ประกอบทั้งสองเข้าด้วยกัน สถานการณ์นี้เรียกว่าการเก็บบัฟเฟอร์ หรือ queue-stuffing กระบวนการแสดงผล ไม่รู้ว่าเกิดอะไรขึ้น ความไม่สอดคล้องกันของอัตราเฟรมจึงแย่ลง หาก เกมอินพุตตัวอย่างก่อนเฟรม ทำให้เวลาในการตอบสนองของการป้อนข้อมูลแย่ลง
ใช้ Android Choreographer เอง
เกมยังใช้ Android Choreographer ด้วยสำหรับการซิงค์ คอมโพเนนต์นี้ ที่มีอยู่ใน Java จาก API 16 และใน C++ จาก API 24 จะแสดงผลตามปกติที่ ความถี่เดียวกับระบบย่อยของดิสเพลย์ เรายังมีรายละเอียดปลีกย่อย เมื่อมีการส่งเครื่องหมายถูกนี้เมื่อเทียบกับ VSYNC ฮาร์ดแวร์จริง และ จะต่างกันไปตามอุปกรณ์ การยัดบัฟเฟอร์อาจยังเกิดขึ้นในเฟรมที่ใช้เวลานาน
ข้อดีของไลบรารี Frame Pacing
ไลบรารีการกำหนดอัตราการแสดงโฆษณาใช้ Android Choreographer สำหรับการซิงค์และ จะดีลกับความแปรปรวนในการจัดส่งเครื่องหมายถูกให้กับคุณ ใช้งานนำเสนอ การประทับเวลาเพื่อให้แน่ใจว่ามีการนำเสนอเฟรมในเวลาที่เหมาะสมและซิงค์ Fences เพื่อป้องกันการยัดเยียดข้อมูล ไลบรารีใช้ นักออกแบบท่าเต้น NDK หากมีให้ใช้งานและ จะกลับไปที่ Java Choreographer ไม่เป็นเช่นนั้น
ไลบรารีจะจัดการกับอัตราการรีเฟรชหลายอัตราการรีเฟรชหากอุปกรณ์รองรับ ซึ่งทำให้เกมมีความยืดหยุ่นในการนำเสนอเฟรมมากขึ้น ตัวอย่างเช่น สำหรับ ที่สนับสนุนอัตราการรีเฟรช 60 Hz และ 90 Hz ซึ่งเป็นเกมที่ไม่สามารถ ที่ผลิต 60 เฟรมต่อวินาทีสามารถลดลงเหลือ 45 FPS แทนที่จะเป็น 30 FPS ยังคงอยู่ อย่างราบรื่น ไลบรารีจะตรวจหาอัตราเฟรมของเกมที่คาดไว้และปรับเฟรมโดยอัตโนมัติ จำนวนครั้งของการนำเสนอให้สอดคล้องกัน ไลบรารี Frame Pacing จะช่วยปรับปรุงแบตเตอรี่ เพราะหลีกเลี่ยงการอัปเดตการแสดงผลที่ไม่จำเป็น ตัวอย่างเช่น หากเกม แสดงผลที่ 60 FPS แต่จอแสดงผลอัปเดตที่ 120 Hz อัปเดต 2 ครั้งสําหรับทุกเฟรม ไลบรารี Frame Pacing สามารถหลีกเลี่ยงได้โดยการตั้งค่า อัตราการรีเฟรชเป็นค่าที่อุปกรณ์รองรับซึ่งอยู่ใกล้กับเป้าหมายมากที่สุด อัตราเฟรม
วิธีการทำงาน
ส่วนต่อไปนี้จะแสดงวิธีที่ไลบรารี Frame Pacing จัดการกับความยาวและ เฟรมสั้นๆ ในเกมเพื่อให้ได้การกำหนดอัตราเฟรมที่ถูกต้อง
ความเร็วเฟรมที่ 30 Hz ถูกต้อง
เมื่อแสดงผลที่ 30 Hz บนอุปกรณ์ 60 Hz สถานการณ์ที่เหมาะสมบน Android คือ ที่แสดงในรูปที่ 1 SurfaceFlinger จะยึดบัฟเฟอร์กราฟิกใหม่ หากมี (NB ใน แผนภาพระบุว่า "ไม่มีบัฟเฟอร์" อยู่และรายการก่อนหน้าซ้ำ)
รูปที่ 1 การกำหนดอัตราเฟรมที่เหมาะสมที่ 30 Hz บนอุปกรณ์ 60 Hz
เฟรมที่สั้นในเกมทำให้กระตุก
เครื่องมือเกมต้องอาศัยนักออกแบบท่าเต้นในอุปกรณ์สมัยใหม่ส่วนใหญ่ ที่กระตุ้นการส่งเฟรม อย่างไรก็ตาม ยังคงมี ความเป็นไปได้ที่การกำหนดจังหวะเฟรมต่ำเนื่องจากเฟรมสั้น ดังที่แสดงในรูปที่ 2 ผู้เล่นจะมองว่าเฟรมสั้นๆ ที่ตามด้วยเฟรมยาวเป็นภาพที่กระตุก
รูปที่ 2 เฟรมเกมสั้นๆ C จะทำให้เฟรม B นำเสนอเพียงเฟรมเดียว ตามด้วยเฟรม C หลายเฟรม
ซึ่งไลบรารี Frame Pacing ช่วยแก้ปัญหานี้ได้โดยใช้การประทับเวลาในการนำเสนอ
ไลบรารีใช้ส่วนขยายการประทับเวลาในงานนำเสนอ
EGL_ANDROID_presentation_time
และ
VK_GOOGLE_display_timing
เพื่อไม่ให้มีการนำเสนอเฟรมตั้งแต่เนิ่นๆ ดังที่แสดงในรูปที่ 3
รูปที่ 3 เกมเฟรม B นำเสนอ 2 ครั้งเพื่อการแสดงผลที่ราบรื่นขึ้น
เฟรมขนาดยาวทำให้วิดีโอติดขัดและตอบสนองช้า
เมื่อภาระงานในการแสดงผลใช้เวลานานกว่าภาระงานของแอปพลิเคชัน ลงในคิวแล้ว ซึ่งจะทำให้เกิดการกระตุก และยังอาจ ทำให้เวลาในการตอบสนองเพิ่มขึ้นเนื่องจากการใส่บัฟเฟอร์ (ดูรูปที่ 4) ทั้งช่วยลบการกระตุกและเฟรมเวลาในการตอบสนองที่เกินมา
รูปที่ 4 เฟรมยาว B ให้จังหวะที่ไม่ถูกต้องสำหรับ 2 เฟรม คือ A และ B
ไลบรารีแก้ปัญหานี้โดยใช้ Sync Fences
(EGL_KHR_fence_sync
และ
VkFence
)
เพื่อแทรกรอในแอปพลิเคชันที่อนุญาตให้ไปป์ไลน์การแสดงผลสามารถตรวจจับ
แทนที่จะให้แรงกดดันด้านหลังเพิ่มมากขึ้น เฟรม A ยังคงนำเสนอ
เฟรมพิเศษ แต่ตอนนี้เฟรม B แสดงได้อย่างถูกต้อง ดังที่แสดงในรูปที่ 5
รูปที่ 5 เฟรม C และ D รอนำเสนอ
โหมดการทำงานที่รองรับ
คุณสามารถกำหนดค่าไลบรารี Frame Pacing ให้ทำงานอย่างใดอย่างหนึ่งใน 3 อย่างนี้ โหมดต่อไปนี้
- ปิดโหมดอัตโนมัติ + ไปป์ไลน์
- โหมดอัตโนมัติเปิดอยู่ + ไปป์ไลน์
- โหมดอัตโนมัติเปิดอยู่ + โหมดไปป์ไลน์อัตโนมัติ (ไปป์ไลน์/ไม่ใช่ไปป์)
โหมดที่แนะนำ
คุณสามารถทดลองด้วยโหมดอัตโนมัติและโหมดไปป์ไลน์ แต่คุณจะเริ่มต้นด้วยการหมุน และรวมรายการต่อไปนี้หลังจากเริ่มต้น Swappy
swappyAutoSwapInterval(false);
swappyAutoPipelineMode(false);
swappyEnableStats(false);
swappySwapIntervalNS(1000000000L/yourPreferredFrameRateInHz);
โหมดไปป์ไลน์
โดยทั่วไปแล้ว ไลบรารีจะใช้โมเดลไปป์ไลน์ เพื่อประสานงานภาระงานของเครื่องมือค้นหา ซึ่งจะแยกภาระงานของ CPU และ GPU ข้ามขอบเขตของ VSYNC
รูปที่ 6 โหมดไปป์ไลน์
โหมดที่ไม่ใช่ไปป์ไลน์
โดยทั่วไป วิธีนี้ส่งผลให้หน้าจอป้อนข้อมูลต่ำลงและคาดเดาได้มากขึ้น เวลาในการตอบสนอง ในกรณีที่เกมใช้เวลาที่ใช้ในการแสดงผลเฟรมต่ำมาก ทั้ง CPU และ GPU ภาระงานอาจพอดีกับช่วงเวลาการสลับระยะเดียว ในกรณีนี้ หน้าเว็บไม่ใช่ท่อ จะส่งผลให้เวลาในการตอบสนองของหน้าจออินพุตต่ำลง
รูปที่ 7 โหมดที่ไม่ใช่ไปป์ไลน์
โหมดอัตโนมัติ
เกมส่วนใหญ่ไม่รู้วิธีเลือกช่วงการสลับ ซึ่งเป็นระยะเวลาสำหรับ แสดงแต่ละเฟรม (เช่น 33.3 มิลลิวินาทีสำหรับ 30 Hz) ในอุปกรณ์บางรุ่น เกมสามารถแสดงผลที่ 60 FPS ในขณะที่อีกเกมหนึ่งจะต้องวางลดลงให้ต่ำกว่านี้ โหมดอัตโนมัติจะวัดเวลาของ CPU และ GPU เพื่อทำสิ่งต่อไปนี้
- เลือกช่วงเวลาการสลับโดยอัตโนมัติ: เกมที่ส่งเสียง 30 Hz ในบางช่วง ฉากและ 60 Hz ในแอปอื่นๆ จะช่วยให้ไลบรารีสามารถปรับช่วงเวลานี้ได้ แบบไดนามิก
- ปิดใช้งานไปป์ไลน์สำหรับเฟรมความเร็วสูง: ให้ประสิทธิภาพสูงสุด เวลาในการตอบสนองของหน้าจออินพุตในทุกกรณี
อัตราการรีเฟรชหลายรายการ
อุปกรณ์ที่รองรับอัตราการรีเฟรชหลายอัตรา มอบความยืดหยุ่นที่มากกว่า การเลือกช่วงเวลาการสลับที่ดูลื่นไหล
- บนอุปกรณ์ 60 Hz: 60 FPS / 30 FPS / 20FPS
- บนอุปกรณ์ 60 Hz + 90 Hz: 90 FPS / 60 FPS / 45 FPS / 30 FPS
- บนอุปกรณ์ 60 Hz + 90 Hz + 120 Hz: 120 FPS / 90 FPS / 60 FPS / 45 FPS / 40 FPS / 30 FPS
ไลบรารีจะเลือกอัตราการรีเฟรชที่ตรงกับการแสดงผลจริงมากที่สุด ระยะเวลาของเฟรมของเกม ให้ประสบการณ์ด้านภาพที่ดียิ่งขึ้น
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดอัตราเฟรมของอัตราการรีเฟรชหลายครั้ง โปรดดู การแสดงผลอัตราการรีเฟรชสูงใน Android บล็อกโพสต์
สถิติเฟรม
ไลบรารี Frame Pacing นำเสนอสถิติต่อไปนี้สำหรับการแก้ไขข้อบกพร่องและ วัตถุประสงค์ในการทำโปรไฟล์:
- ฮิสโตแกรมของจำนวนการรีเฟรชหน้าจอที่เฟรมหนึ่งรออยู่ใน คอมโพสิเตอร์คิวหลังจากการแสดงผลเสร็จสิ้น
- ฮิสโตแกรมของจำนวนการรีเฟรชหน้าจอที่ส่งระหว่างคำขอ และเวลาที่นำเสนอจริงและเวลาปัจจุบัน
- ฮิสโตแกรมของจำนวนการรีเฟรชหน้าจอที่ส่งผ่านระหว่าง 2 ครั้งต่อๆ ไป ของเฟรม
- ฮิสโตแกรมของจำนวนการรีเฟรชหน้าจอที่ส่งผ่านระหว่างจุดเริ่มต้นของ การทำงานของ CPU สำหรับเฟรมนี้และเวลาปัจจุบันจริง
ขั้นตอนถัดไป
ดูคำแนะนำอย่างใดอย่างหนึ่งต่อไปนี้ในการผสานรวมไลบรารี Android Frame Pacing ในเกมของคุณ:
- ผสานรวมการกำหนดอัตราการแสดงโฆษณาของ Android Frame เข้ากับโหมดแสดงภาพ OpenGL
- ผสานรวม Android Frame Pacing กับโหมดแสดงภาพ Vulkan