Khung đồng bộ hoá

Khung đồng bộ hoá mô tả rõ ràng các phần phụ thuộc giữa các thao tác không đồng bộ khác nhau trong hệ thống đồ hoạ Android. Khung này cung cấp một API cho phép các thành phần cho biết thời điểm vùng đệm được giải phóng. Khung này cũng cho phép truyền các nguyên tắc đồng bộ hoá giữa các trình điều khiển từ nhân đến không gian người dùng và giữa các quy trình không gian người dùng.

Ví dụ: một ứng dụng có thể xếp hàng các thao tác sẽ được thực hiện trong GPU. GPU bắt đầu vẽ hình ảnh đó. Mặc dù hình ảnh chưa được vẽ vào bộ nhớ, nhưng con trỏ vùng đệm được truyền đến trình kết hợp cửa sổ cùng với một hàng rào cho biết thời điểm GPU sẽ hoàn tất công việc. Trình kết hợp cửa sổ bắt đầu xử lý trước thời hạn và chuyển công việc cho bộ điều khiển màn hình. Tương tự, công việc của CPU sẽ được thực hiện trước thời hạn. Sau khi GPU hoàn tất, bộ điều khiển màn hình sẽ hiển thị ngay hình ảnh.

Khung đồng bộ hoá cũng cho phép người triển khai tận dụng các tài nguyên đồng bộ hoá trong các thành phần phần cứng của riêng họ. Cuối cùng, khung này cung cấp khả năng hiển thị vào quy trình đồ hoạ để hỗ trợ gỡ lỗi.

Đồng bộ hoá rõ ràng

Tính năng đồng bộ hoá rõ ràng cho phép nhà sản xuất và người tiêu dùng vùng đệm đồ hoạ báo hiệu khi họ dùng xong một vùng đệm. Quá trình đồng bộ hoá rõ ràng được triển khai trong không gian nhân.

Sau đây là những lợi ích của việc đồng bộ hoá rõ ràng:

  • Ít có sự khác biệt về hành vi giữa các thiết bị
  • Hỗ trợ gỡ lỗi hiệu quả hơn
  • Cải thiện các chỉ số kiểm thử

Khung đồng bộ hoá có 3 loại đối tượng:

  • sync_timeline
  • sync_pt
  • sync_fence

sync_timeline

sync_timeline là một dòng thời gian tăng đơn điệu mà các nhà cung cấp nên triển khai cho từng phiên bản trình điều khiển, chẳng hạn như ngữ cảnh GL, bộ điều khiển màn hình hoặc bộ kết hợp 2D. sync_timeline đếm số lượng công việc được gửi đến nhân cho một phần cứng cụ thể. sync_timeline đảm bảo về thứ tự của các thao tác và cho phép triển khai theo từng phần cứng.

Hãy tuân theo các nguyên tắc sau khi triển khai sync_timeline:

  • Cung cấp tên hữu ích cho tất cả các trình điều khiển, dòng thời gian và hàng rào để đơn giản hoá việc gỡ lỗi.
  • Triển khai các toán tử timeline_value_strpt_value_str trong dòng thời gian để giúp kết quả gỡ lỗi dễ đọc hơn.
  • Triển khai lệnh điền driver_data để cấp cho các thư viện không gian người dùng (chẳng hạn như thư viện GL) quyền truy cập vào dữ liệu dòng thời gian riêng tư (nếu muốn). data_driver cho phép nhà cung cấp truyền thông tin về sync_fencesync_pts bất biến để tạo dòng lệnh dựa trên các thông tin đó.
  • Không cho phép không gian người dùng tạo hoặc báo hiệu rõ ràng một hàng rào. Việc tạo rõ ràng các tín hiệu/hàng rào sẽ dẫn đến một cuộc tấn công từ chối dịch vụ làm dừng chức năng của quy trình.
  • Không truy cập rõ ràng vào các phần tử sync_timeline, sync_pt hoặc sync_fence. API này cung cấp tất cả các chức năng bắt buộc.

sync_pt

sync_pt là một giá trị hoặc điểm duy nhất trên sync_timeline. Một điểm có 3 trạng thái: đang hoạt động, được báo hiệu và lỗi. Các điểm bắt đầu ở trạng thái hoạt động và chuyển sang trạng thái được báo hiệu hoặc trạng thái lỗi. Ví dụ: khi một ứng dụng sử dụng hình ảnh không còn cần vùng đệm nữa, một sync_pt sẽ được báo hiệu để ứng dụng tạo hình ảnh biết rằng có thể ghi lại vào vùng đệm.

sync_fence

sync_fence là một tập hợp các giá trị sync_pt thường có các đối tượng sync_timeline mẹ khác nhau (chẳng hạn như đối với bộ điều khiển màn hình và GPU). sync_fence, sync_ptsync_timeline là các thành phần cơ bản chính mà trình điều khiển và không gian người dùng sử dụng để truyền đạt các phần phụ thuộc của chúng. Khi một hàng rào được báo hiệu, tất cả các lệnh được đưa ra trước hàng rào đều được đảm bảo hoàn tất vì trình điều khiển hạt nhân hoặc khối phần cứng thực thi các lệnh theo thứ tự.

Khung đồng bộ hoá cho phép nhiều thực thể tiêu thụ hoặc thực thể tạo tín hiệu khi chúng hoàn tất việc sử dụng một vùng đệm, truyền đạt thông tin về phần phụ thuộc bằng một tham số hàm. Hàng rào được hỗ trợ bằng một bộ mô tả tệp và được truyền từ không gian nhân đến không gian người dùng. Ví dụ: một hàng rào có thể chứa hai giá trị sync_pt cho biết thời điểm hai người dùng hình ảnh riêng biệt đọc xong một vùng đệm. Khi hàng rào được báo hiệu, nhà sản xuất hình ảnh biết rằng cả hai người dùng đều đã hoàn tất việc sử dụng.

Hàng rào, chẳng hạn như các giá trị sync_pt, bắt đầu hoạt động và thay đổi trạng thái dựa trên trạng thái của các điểm. Nếu tất cả các giá trị sync_pt đều được báo hiệu, thì sync_fence sẽ được báo hiệu. Nếu một sync_pt rơi vào trạng thái lỗi, thì toàn bộ sync_fence sẽ ở trạng thái lỗi.

Sau khi tạo hàng rào, bạn sẽ không thể thay đổi thành viên trong sync_fence. Để có nhiều điểm trong một hàng rào, bạn cần hợp nhất các điểm từ 2 hàng rào riêng biệt vào một hàng rào thứ ba. Nếu một trong các điểm đó được báo hiệu trong hàng rào ban đầu và điểm còn lại thì không, thì hàng rào thứ ba cũng sẽ không ở trạng thái được báo hiệu.

Để triển khai quá trình đồng bộ hoá rõ ràng, hãy cung cấp những thông tin sau:

  • Một hệ thống con trong không gian nhân triển khai khung đồng bộ hoá cho một trình điều khiển phần cứng cụ thể. Các trình điều khiển cần nhận biết hàng rào thường là mọi thứ truy cập hoặc giao tiếp với Trình kết hợp phần cứng. Các tệp chính bao gồm:
    • Triển khai cốt lõi:
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • Tài liệu tại kernel/common/Documentation/sync.txt
    • Thư viện để giao tiếp với không gian nhân trong platform/system/core/libsync
  • Nhà cung cấp phải cung cấp các hàng rào đồng bộ hoá thích hợp làm tham số cho các hàm validateDisplay()presentDisplay() trong HAL.
  • Hai tiện ích GL liên quan đến hàng rào (EGL_ANDROID_native_fence_syncEGL_ANDROID_wait_sync) và khả năng hỗ trợ hàng rào trong trình điều khiển đồ hoạ.

Nghiên cứu điển hình: Triển khai trình điều khiển màn hình

Để sử dụng API hỗ trợ chức năng đồng bộ hoá, hãy phát triển một trình điều khiển màn hình có chức năng vùng đệm hiển thị. Trước khi có khung đồng bộ hoá, hàm này sẽ nhận các đối tượng dma-buf, đặt các vùng đệm đó lên màn hình và chặn trong khi vùng đệm hiển thị. Ví dụ:

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

Với khung đồng bộ hoá, hàm display_buffer sẽ phức tạp hơn. Trong khi đặt một vùng đệm trên màn hình, vùng đệm sẽ được liên kết với một hàng rào cho biết thời điểm vùng đệm sẽ sẵn sàng. Bạn có thể xếp hàng và bắt đầu công việc sau khi hàng rào được xoá.

Việc xếp hàng đợi và bắt đầu công việc sau khi hàng rào được xoá sẽ không chặn bất cứ thứ gì. Bạn sẽ trả lại ngay hàng rào của riêng mình, đảm bảo thời điểm vùng đệm sẽ nằm ngoài màn hình. Khi bạn xếp hàng các vùng đệm, nhân sẽ liệt kê các phần phụ thuộc bằng khung đồng bộ hoá:

/*
 * 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);

Tích hợp tính năng đồng bộ hoá

Phần này giải thích cách tích hợp khung đồng bộ hoá không gian nhân với các phần không gian người dùng của khung Android và các trình điều khiển phải giao tiếp với nhau. Các đối tượng trong không gian nhân được biểu thị dưới dạng bộ mô tả tệp trong không gian người dùng.

Quy ước tích hợp

Tuân theo các quy ước về giao diện HAL của Android:

  • Nếu API cung cấp một bộ mô tả tệp tham chiếu đến sync_pt, thì trình điều khiển của nhà cung cấp hoặc HAL sử dụng API phải đóng bộ mô tả tệp.
  • Nếu trình điều khiển của nhà cung cấp hoặc HAL truyền một bộ mô tả tệp chứa sync_pt đến một hàm API, thì trình điều khiển của nhà cung cấp hoặc HAL không được đóng bộ mô tả tệp.
  • Để tiếp tục sử dụng chỉ số mô tả tệp hàng rào, trình điều khiển của nhà cung cấp hoặc HAL phải sao chép chỉ số mô tả.

Đối tượng hàng rào được đổi tên mỗi khi đi qua BufferQueue. Tính năng hỗ trợ hàng rào của nhân cho phép hàng rào có các chuỗi cho tên, vì vậy, khung đồng bộ hoá sẽ dùng tên cửa sổ và chỉ mục vùng đệm đang được xếp hàng đợi để đặt tên cho hàng rào, chẳng hạn như SurfaceView:0. Điều này hữu ích trong quá trình gỡ lỗi để xác định nguồn gốc của một bế tắc vì tên xuất hiện trong đầu ra của /d/sync và báo cáo lỗi.

Tích hợp ANativeWindow

ANativeWindow nhận biết được hàng rào. dequeueBuffer, queueBuffercancelBuffer có các tham số hàng rào.

Tích hợp OpenGL ES

Hoạt động tích hợp đồng bộ hoá OpenGL ES dựa trên 2 tiện ích EGL:

  • EGL_ANDROID_native_fence_sync cung cấp một cách để bao bọc hoặc tạo các bộ mô tả tệp hàng rào Android gốc trong các đối tượng EGLSyncKHR.
  • EGL_ANDROID_wait_sync cho phép các tắc nghẽn phía GPU thay vì phía CPU, khiến GPU phải chờ EGLSyncKHR. Phần mở rộng EGL_ANDROID_wait_sync giống với phần mở rộng EGL_KHR_wait_sync.

Để sử dụng các tiện ích này một cách độc lập, hãy triển khai tiện ích EGL_ANDROID_native_fence_sync cùng với sự hỗ trợ của nhân liên kết. Tiếp theo, hãy bật tiện ích EGL_ANDROID_wait_sync trong trình điều khiển. Tiện ích EGL_ANDROID_native_fence_sync bao gồm một loại đối tượng EGLSyncKHR riêng biệt. Do đó, các tiện ích áp dụng cho các EGLSyncKHR loại đối tượng hiện có không nhất thiết phải áp dụng cho các đối tượng EGL_ANDROID_native_fence, tránh các lượt tương tác không mong muốn.

Tiện ích EGL_ANDROID_native_fence_sync sử dụng một thuộc tính tương ứng của trình mô tả tệp hàng rào gốc. Thuộc tính này chỉ có thể được đặt tại thời điểm tạo và không thể được truy vấn trực tiếp từ một đối tượng đồng bộ hoá hiện có. Bạn có thể đặt thuộc tính này thành một trong hai chế độ:

  • Một giá trị mô tả tệp hàng rào hợp lệ bao bọc một giá trị mô tả tệp hàng rào Android gốc hiện có trong một đối tượng EGLSyncKHR.
  • -1 tạo một chỉ số mô tả tệp hàng rào Android gốc từ một đối tượng EGLSyncKHR.

Dùng lệnh gọi hàm DupNativeFenceFD() để trích xuất đối tượng EGLSyncKHR từ trình mô tả tệp hàng rào Android gốc. Thao tác này có kết quả tương tự như việc truy vấn thuộc tính tập hợp, nhưng tuân theo quy ước rằng người nhận đóng hàng rào (do đó, thao tác trùng lặp). Cuối cùng, việc huỷ đối tượng EGLSyncKHR sẽ đóng thuộc tính hàng rào nội bộ.

Tích hợp Hardware Composer

Hardware Composer xử lý 3 loại hàng rào đồng bộ hoá:

  • Hàng rào thu được được truyền cùng với các vùng đệm đầu vào đến các lệnh gọi setLayerBuffersetClientTarget. Các khoá này đại diện cho một thao tác ghi đang chờ xử lý vào vùng đệm và phải báo hiệu trước khi SurfaceFlinger hoặc HWC cố gắng đọc từ vùng đệm được liên kết để thực hiện thành phần.
  • Hàng rào phát hành được truy xuất sau khi gọi đến presentDisplay bằng lệnh gọi getReleaseFences. Những đối tượng này đại diện cho một thao tác đọc đang chờ xử lý từ vùng đệm trước đó trên cùng một lớp. Một tín hiệu hàng rào phát hành khi HWC không còn sử dụng vùng đệm trước đó nữa vì vùng đệm hiện tại đã thay thế vùng đệm trước đó trên màn hình. Hàng rào phát hành được truyền trở lại ứng dụng cùng với các vùng đệm trước đó sẽ được thay thế trong quá trình kết hợp hiện tại. Ứng dụng phải đợi cho đến khi có tín hiệu hàng rào phát hành trước khi ghi nội dung mới vào vùng đệm đã được trả về cho ứng dụng.
  • Present fences được trả về, mỗi khung hình một hàng rào, trong lệnh gọi đến presentDisplay. Hàng rào hiện tại biểu thị thời điểm quá trình kết hợp khung hình này đã hoàn tất hoặc thời điểm kết quả kết hợp của khung hình trước không còn cần thiết nữa. Đối với màn hình thực, presentDisplay sẽ trả về các hàng rào hiện tại khi khung hình hiện tại xuất hiện trên màn hình. Sau khi các hàng rào hiện tại được trả về, bạn có thể ghi lại vào vùng đệm mục tiêu SurfaceFlinger nếu có thể. Đối với màn hình ảo, các hàng rào hiện tại sẽ được trả về khi có thể đọc từ vùng đệm đầu ra một cách an toàn.