ไลบรารีการกำหนดอัตราการแสดงโฆษณาเฟรม เป็นส่วนหนึ่งของชุดเครื่องมือพัฒนาเกม 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 ใน แผนภาพระบุว่า "ไม่มีบัฟเฟอร์" อยู่และรายการก่อนหน้าซ้ำ)

การกำหนดอัตราเฟรมที่เหมาะสมที่ 30 Hz บนอุปกรณ์ 60 Hz

รูปที่ 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 ในเกมของคุณ: