เฟรมเวิร์กการซิงค์

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

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

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

การซิงค์ที่ชัดเจน

การซิงค์ข้อมูลที่ชัดเจนจะช่วยให้ผู้ผลิตและผู้บริโภคบัฟเฟอร์กราฟิก เพื่อส่งสัญญาณแจ้งเมื่อใช้บัฟเฟอร์เสร็จแล้ว การซิงค์อย่างชัดเจนคือ ใน Kernel-Space

ประโยชน์ของการซิงค์ข้อมูลอย่างชัดเจนมีดังนี้

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

เฟรมเวิร์กการซิงค์มีออบเจ็กต์ 3 ประเภทดังนี้

  • sync_timeline
  • sync_pt
  • sync_fence

ไทม์ไลน์การซิงค์

sync_timeline คือไทม์ไลน์ที่เพิ่มขึ้นอย่างเดียวซึ่งผู้ให้บริการควรนำมาใช้กับอินสแตนซ์ของไดรเวอร์แต่ละรายการ เช่น บริบท GL, ตัวควบคุมจอแสดงผล หรือ 2D blitter จำนวน sync_timeline รายการ งานที่ส่งไปยังเคอร์เนลสำหรับฮาร์ดแวร์หนึ่งๆ sync_timeline ให้การรับประกันเกี่ยวกับลําดับการดําเนินการ และช่วยให้ติดตั้งใช้งานกับฮาร์ดแวร์ได้

โปรดทำตามหลักเกณฑ์เหล่านี้เมื่อใช้ sync_timeline

  • ตั้งชื่อที่เป็นประโยชน์สำหรับไดรเวอร์ ไทม์ไลน์ และรั้วทั้งหมดเพื่อลดความซับซ้อนในการแก้ไขข้อบกพร่อง
  • ใช้โอเปอเรเตอร์ timeline_value_str และ pt_value_str ในไทม์ไลน์เพื่อให้เอาต์พุตการแก้ไขข้อบกพร่องอ่านง่ายขึ้น
  • ใช้การเติม driver_data เพื่อให้คลังพื้นที่ผู้ใช้ เช่น คลัง GL มีสิทธิ์เข้าถึงข้อมูลไทม์ไลน์ส่วนตัว หากต้องการ data_driver ช่วยให้ผู้ให้บริการส่งข้อมูลเกี่ยวกับ sync_fence และ sync_pts ที่ไม่เปลี่ยนแปลงเพื่อสร้างบรรทัดคำสั่งตามข้อมูลดังกล่าวได้
  • อย่าอนุญาตให้พื้นที่ผู้ใช้สร้างหรือส่งสัญญาณรั้วอย่างชัดแจ้ง ชัดเจน การสร้างสัญญาณ/รั้วจะทำให้เกิดการโจมตีแบบปฏิเสธการให้บริการ หยุดฟังก์ชันการทำงานของไปป์ไลน์
  • ไม่เข้าถึง sync_timeline, sync_pt หรือ sync_fence องค์ประกอบอย่างชัดเจน API มีฟังก์ชันที่จำเป็นทั้งหมด

sync_pt

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

sync_fence

sync_fence คือคอลเล็กชันที่มี sync_pt ค่า บ่อยครั้ง มี sync_timeline หลักที่แตกต่างกัน (เช่น สำหรับจอแสดงผล ตัวควบคุมและ GPU) sync_fence, sync_pt และ sync_timeline คือค่าพื้นฐานหลักๆ ที่ไดรเวอร์และพื้นที่ผู้ใช้ ใช้สื่อสารทรัพยากร Dependency ได้ เมื่อมีการแจ้งสัญญาณของรั้ว คำสั่งทั้งหมดที่ออกก่อนรั้วจะเสร็จสมบูรณ์อย่างแน่นอน เนื่องจากไดรเวอร์เคอร์เนลหรือบล็อกฮาร์ดแวร์จะดำเนินการตามคำสั่งตามลำดับ

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

รั้ว เช่น ค่า sync_pt จะเริ่มต้นใช้งานอยู่และเปลี่ยนสถานะตาม สถานะคะแนน หากค่า sync_pt ทั้งหมดมีสัญญาณ ระบบจะส่งสัญญาณให้กับ sync_fence หาก sync_pt รายการใดรายการหนึ่งอยู่ในสถานะข้อผิดพลาด sync_fence ทั้งหมดจะอยู่ในสถานะข้อผิดพลาด

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

ในการใช้การซิงค์ข้อมูลอย่างชัดเจน โปรดระบุข้อมูลต่อไปนี้

  • ระบบย่อยในพื้นที่เคอร์เนลที่ใช้เฟรมเวิร์กการซิงค์สำหรับไดรเวอร์ฮาร์ดแวร์หนึ่งๆ คนขับที่ต้องระวังรั้ว โดยทั่วไปแล้วทุกสิ่งที่เข้าถึงหรือสื่อสารกับฮาร์ดแวร์คอมโพสเซอร์ ไฟล์หลักๆ ได้แก่
    • การใช้งานหลัก
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • เอกสารประกอบที่ kernel/common/Documentation/sync.txt
    • ไลบรารีสำหรับสื่อสารกับพื้นที่ของเคอร์เนลใน platform/system/core/libsync
  • ผู้ให้บริการต้องระบุการจำกัดเวลาการซิงค์ที่เหมาะสมเป็นพารามิเตอร์ให้กับฟังก์ชัน validateDisplay() และ presentDisplay() ใน HAL
  • ส่วนขยาย GL ที่เกี่ยวข้องกับรั้ว 2 รายการ (EGL_ANDROID_native_fence_sync และ EGL_ANDROID_wait_sync) และการรองรับรั้วในโปรแกรมควบคุมกราฟิก

กรณีศึกษา: ติดตั้งใช้งานโปรแกรมควบคุมการแสดงผล

หากต้องการใช้ API ที่รองรับฟังก์ชันการซิงค์ พัฒนาไดรเวอร์จอแสดงผลที่มีฟังก์ชันบัฟเฟอร์จอแสดงผล ก่อนการเปลี่ยนแปลง มีเฟรมเวิร์กการซิงค์อยู่แล้ว ฟังก์ชันนี้จะได้รับ dma-buf วางบัฟเฟอร์เหล่านั้นบนจอแสดงผล และบล็อกขณะที่เห็นบัฟเฟอร์ สำหรับ ตัวอย่าง:

/*
 * assumes buffer is ready to be displayed.  returns when buffer is no longer on
 * screen.
 */
void display_buffer(struct dma_buf *buffer);

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

การจัดคิวและเริ่มต้นงานหลังจากเคลียร์รั้วแล้วจะไม่บล็อกอะไรเลย คุณจะต้องคืนรั้วของตัวเองทันที ซึ่งรับประกันได้ว่าจะมีการบัฟเฟอร์ จะอยู่นอกจอแสดงผล เมื่อคุณจัดคิวบัฟเฟอร์ เคอร์เนลจะแสดงรายการ ทรัพยากร Dependency ด้วยเฟรมเวิร์กการซิงค์

/*
 * displays buffer when fence is signaled.  returns immediately with a fence
 * that signals when buffer is no longer displayed.
 */
struct sync_fence* display_buffer(struct dma_buf *buffer, struct sync_fence
*fence);

การผสานรวมการซิงค์

ส่วนนี้จะอธิบายวิธีผสานรวมเฟรมเวิร์กการซิงค์พื้นที่เคอร์เนลกับ ส่วนของพื้นที่ผู้ใช้ของเฟรมเวิร์ก Android และไดรเวอร์ที่ต้องสื่อสาร ให้กันและกัน ออบเจ็กต์ช่องว่างของเคอร์เนลแสดงเป็นข้อบ่งชี้ไฟล์ใน พื้นที่ผู้ใช้

แบบแผนการรวม

ทำตามรูปแบบอินเทอร์เฟซ HAL ของ Android ดังนี้

  • หาก API มีข้อบ่งชี้ไฟล์ที่อ้างถึง sync_pt ไดรเวอร์ของผู้ให้บริการหรือ HAL ที่ใช้ API ต้องปิดข้อบ่งชี้ไฟล์
  • หากโปรแกรมควบคุมของผู้ให้บริการหรือ HAL ส่งตัวระบุไฟล์ที่มี sync_pt ไปยังฟังก์ชัน API โปรแกรมควบคุมของผู้ให้บริการหรือ HAL ต้องไม่ปิดตัวระบุไฟล์
  • หากต้องการใช้ตัวบ่งชี้ไฟล์รั้วต่อไป ไดรเวอร์ของผู้ให้บริการหรือ HAL จะต้องทำซ้ำตัวบ่งชี้

ระบบจะเปลี่ยนชื่อออบเจ็กต์รั้วทุกครั้งที่ผ่าน BufferQueue การรองรับรั้วเคอร์เนลช่วยให้รั้วมีสตริงสำหรับชื่อได้ ดังนั้นเฟรมเวิร์กการซิงค์จะใช้ชื่อกรอบเวลาและดัชนีบัฟเฟอร์ที่อยู่ในคิวเพื่อตั้งชื่อรั้ว เช่น SurfaceView:0 ซึ่งมีประโยชน์ในการแก้ไขข้อบกพร่องเพื่อระบุแหล่งที่มาของการล็อกตาย เนื่องจากชื่อจะปรากฏในเอาต์พุตของ /d/sync และรายงานข้อบกพร่อง

การผสานรวม ANativeWindow

ANativeWindow รับรู้รั้ว dequeueBuffer, queueBuffer และ cancelBuffer มีพารามิเตอร์รั้ว

การผสานรวม OpenGL ES

การผสานรวมการซิงค์ OpenGL ES ต้องใช้ส่วนขยาย EGL 2 รายการดังนี้

  • EGL_ANDROID_native_fence_sync มีวิธีในการรวมหรือสร้างตัวบ่งชี้ไฟล์รั้วของ Android ดั้งเดิมในออบเจ็กต์ EGLSyncKHR
  • EGL_ANDROID_wait_sync อนุญาตคอลัมน์ฝั่ง GPU แทนที่จะเป็นฝั่ง CPU ทำให้ GPU รอ EGLSyncKHR ส่วนขยาย EGL_ANDROID_wait_sync เหมือนกับ ส่วนขยาย EGL_KHR_wait_sync

หากต้องการใช้ส่วนขยายเหล่านี้แยกต่างหาก ให้ใช้ ส่วนขยาย EGL_ANDROID_native_fence_sync รายการพร้อมด้วยส่วนขยายที่เกี่ยวข้อง การสนับสนุนเคอร์เนล ต่อไป ให้เปิดใช้ EGL_ANDROID_wait_sync ในไดรเวอร์ของคุณ ส่วนขยาย EGL_ANDROID_native_fence_sync ประกอบด้วยประเภทออบเจ็กต์รั้ว EGLSyncKHR เนทีฟที่แยกต่างหาก ด้วยเหตุนี้ ส่วนขยายที่ใช้กับ EGLSyncKHR ที่มีอยู่ ไม่จำเป็นต้องใช้ประเภทออบเจ็กต์กับ EGL_ANDROID_native_fence เพื่อหลีกเลี่ยงการโต้ตอบที่ไม่ต้องการ

ส่วนขยาย EGL_ANDROID_native_fence_sync ใช้โฆษณาเนทีฟที่เกี่ยวข้อง แอตทริบิวต์ข้อบ่งชี้ไฟล์ fence ที่ตั้งค่าได้เฉพาะตอนที่สร้างและ คุณจะค้นหาจากออบเจ็กต์การซิงค์ที่มีอยู่โดยตรงไม่ได้อีกต่อไป แอตทริบิวต์นี้ สามารถตั้งค่าเป็น 1 ใน 2 โหมดต่อไปนี้

  • ข้อบ่งชี้ไฟล์รั้วที่ถูกต้องรวมโฆษณาเนทีฟที่มีอยู่ ข้อบ่งชี้ไฟล์ fence ของ Android ในออบเจ็กต์ EGLSyncKHR
  • -1 สร้างตัวบ่งชี้ไฟล์รั้วของ Android ดั้งเดิมจากออบเจ็กต์ EGLSyncKHR

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

การผสานรวมฮาร์ดแวร์คอมโพสเซอร์

เครื่องมือประกอบฮาร์ดแวร์จัดการรั้วการซิงค์ 3 ประเภท ได้แก่

  • มองหารั้วจะส่งไปพร้อมกับบัฟเฟอร์อินพุตไปยัง สายจาก setLayerBuffer และ setClientTarget ซึ่งแสดงถึงการเขียนที่รอดำเนินการลงในบัฟเฟอร์และต้องส่งสัญญาณก่อน SurfaceFlinger หรือ HWC พยายามอ่านจากบัฟเฟอร์ที่เกี่ยวข้องไปยัง ทำการเรียบเรียง
  • มีการเรียกรั้วกั้นหลังการโทรเพื่อ presentDisplay โดยใช้การโทร getReleaseFences ค่าเหล่านี้แสดงถึงการอ่านที่รอดำเนินการจากบัฟเฟอร์ก่อนหน้าในเลเยอร์เดียวกัน สัญญาณการปล่อยรั้วจะส่งสัญญาณเมื่อ HWC ไม่ได้ใช้บัฟเฟอร์ก่อนหน้าอีกต่อไปเนื่องจากบัฟเฟอร์ปัจจุบันได้แทนที่บัฟเฟอร์ก่อนหน้าบนจอแสดงผลแล้ว ระบบจะส่งคืนรั้วสำหรับปล่อยกลับไปยังแอปพร้อมกับบัฟเฟอร์ก่อนหน้านี้ที่ จะถูกแทนที่ในระหว่างการแต่งปัจจุบัน โดยแอปจะต้องรอจนกว่า ปล่อยสัญญาณรั้วก่อนที่จะเขียนเนื้อหาใหม่ลงในบัฟเฟอร์ คืนให้กับพวกเขา
  • รั้วปัจจุบันจะแสดงแบบ 1 รายการต่อเฟรม ซึ่งเป็นส่วนหนึ่งของ การโทรไปยัง presentDisplay รั้วเวลาปัจจุบันแสดงถึงเวลาที่การคอมโพสเฟรมนี้เสร็จสมบูรณ์ หรือเมื่อไม่จําเป็นต้องใช้ผลลัพธ์การคอมโพสของเฟรมก่อนหน้าอีกต่อไป สำหรับจับต้องได้ presentDisplay จะแสดงผลรั้วปัจจุบันเมื่อ เฟรมปัจจุบันจะปรากฏขึ้นบนหน้าจอ หลังจากการล้อมรั้วปัจจุบันแล้ว สามารถเขียนไปยังบัฟเฟอร์เป้าหมายของ SurfaceFlinger อีกครั้งได้ หาก ที่เกี่ยวข้อง สําหรับจอแสดงผลเสมือน ระบบจะแสดงรั้วที่แสดงอยู่เมื่ออ่านจากบัฟเฟอร์เอาต์พุตได้อย่างปลอดภัย