เฟรมเวิร์กการซิงค์จะอธิบายการพึ่งพาระหว่างการดำเนินการแบบไม่พร้อมกันที่แตกต่างกันในระบบกราฟิก 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 อีกครั้งได้ หาก ที่เกี่ยวข้อง สําหรับจอแสดงผลเสมือน ระบบจะแสดงรั้วที่แสดงอยู่เมื่ออ่านจากบัฟเฟอร์เอาต์พุตได้อย่างปลอดภัย