กรอบการซิงโครไนซ์

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

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

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

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

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

ประโยชน์ของการซิงโครไนซ์อย่างชัดแจ้ง ได้แก่:

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

กรอบงานการซิงค์มีสามประเภทอ็อบเจ็กต์:

  • sync_timeline
  • sync_pt
  • sync_fence

sync_timeline

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

ทำตามคำแนะนำเหล่านี้เมื่อใช้ sync_timeline :

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

sync_pt

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

sync_fence

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

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

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

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

ในการใช้การซิงโครไนซ์อย่างชัดแจ้ง ให้จัดเตรียมสิ่งต่อไปนี้:

  • ระบบย่อยพื้นที่เคอร์เนลที่ใช้เฟรมเวิร์กการซิงค์สำหรับไดรเวอร์ฮาร์ดแวร์เฉพาะ ไดรเวอร์ที่ต้องตระหนักถึงรั้วโดยทั่วไปคือสิ่งที่เข้าถึงหรือสื่อสารกับ Hardware Composer ไฟล์สำคัญ ได้แก่ :
    • การใช้งานหลัก:
      • 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 ( 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 ฟังก์ชั่นที่มีความซับซ้อนมากขึ้น ขณะวางบัฟเฟอร์บนจอแสดงผล บัฟเฟอร์จะเชื่อมโยงกับรั้วที่ระบุว่าเมื่อใดที่บัฟเฟอร์จะพร้อม คุณสามารถจัดคิวและเริ่มงานได้หลังจากที่รั้วเคลียร์

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

/*
 * 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 และไดรเวอร์ที่ต้องสื่อสารระหว่างกัน ออบเจ็กต์ Kernel-space จะแสดงเป็นตัวอธิบายไฟล์ใน userspace

อนุสัญญาบูรณาการ

ปฏิบัติตามข้อตกลงอินเทอร์เฟซ Android HAL:

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

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

การรวม ANativeWindow

ANativeWindow ตระหนักถึงรั้ว dequeueBuffer , queueBuffer และ cancelBuffer มีพารามิเตอร์ที่รั้ว

การรวม OpenGL ES

การรวมการซิงค์ OpenGL ES อาศัยส่วนขยาย EGL สองรายการ:

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

  • บ่งแฟ้มที่ถูกต้องรั้วล้อมพื้นเมือง Android อธิบายไฟล์รั้วที่มีอยู่ใน EGLSyncKHR วัตถุ
  • -1 สร้างพื้นเมืองไฟล์ Android รั้วบ่งจาก EGLSyncKHR วัตถุ

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

การรวมฮาร์ดแวร์ Composer

Hardware Composer จัดการการซิงค์รั้วสามประเภท:

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