Triển khai Vulkan

Vulkan là API nhiều nền tảng, mức hao tổn thấp dành cho đồ hoạ 3D hiệu suất cao. Giống như OpenGL ES (GLES), Vulkan cung cấp các công cụ để tạo đồ hoạ chất lượng cao, theo thời gian thực trong các ứng dụng. Ưu điểm của việc sử dụng Vulkan là giảm mức hao tổn CPU và hỗ trợ ngôn ngữ Trung gian nhị phân SPIR-V.

Để triển khai thành công Vulkan, thiết bị phải có:

  • Trình tải Vulkan do Android cung cấp.
  • Trình điều khiển Vulkan do các SoC (chẳng hạn như IHV GPU) cung cấp, triển khai API Vulkan. Để hỗ trợ chức năng Vulkan, thiết bị Android cần có phần cứng GPU có thể dùng Vulkan và trình điều khiển liên quan. GPU cũng phải hỗ trợ GLES 3.1 trở lên. Hãy tham khảo ý kiến của nhà cung cấp SoC để yêu cầu hỗ trợ trình điều khiển.

Nếu có trình điều khiển Vulkan, thiết bị cần khai báo các tính năng hệ thống FEATURE_VULKAN_HARDWARE_LEVELFEATURE_VULKAN_HARDWARE_VERSION, với các phiên bản phản ánh chính xác chức năng của thiết bị. Điều này giúp đảm bảo rằng thiết bị tuân thủ Tài liệu định nghĩa về khả năng tương thích (CDD).

Trình tải Vulkan

Trình tải Vulkan platform/frameworks/native/vulkan là giao diện chính giữa các ứng dụng Vulkan và trình điều khiển Vulkan của thiết bị. Trình tải Vulkan được cài đặt tại /system/lib[64]/libvulkan.so. Trình tải cung cấp các điểm truy cập API Vulkan cốt lõi, các điểm truy cập của các tiện ích mà CDD Android yêu cầu và nhiều tiện ích bổ sung không bắt buộc. Trình tải sẽ xuất các tiện ích Tích hợp hệ thống cửa sổ (WSI) và chủ yếu triển khai các tiện ích này trong trình tải thay vì trong trình điều khiển. Trình tải cũng hỗ trợ liệt kê và tải các lớp có thể hiển thị các tiện ích bổ sung và chặn các lệnh gọi API cốt lõi trên đường đến trình điều khiển.

NDK có một thư viện libvulkan.so mã giả lập để liên kết. Thư viện xuất các ký hiệu giống như trình tải. Các ứng dụng gọi các hàm được xuất từ thư viện libvulkan.so thực để nhập các hàm đàn hồi vào trình tải. Các hàm này sẽ gửi đến lớp hoặc trình điều khiển thích hợp dựa trên đối số đầu tiên của chúng. Lệnh gọi vkGet*ProcAddr() trả về con trỏ hàm mà các trampoline điều phối (tức là lệnh gọi trực tiếp vào mã API cốt lõi). Việc gọi thông qua các con trỏ hàm (thay vì các ký hiệu được xuất) sẽ hiệu quả hơn vì bỏ qua thành phần phản hồi và điều phối.

Liệt kê và tải trình điều khiển

Khi hình ảnh hệ thống được tạo, Android sẽ yêu cầu hệ thống biết GPU nào có sẵn. Trình tải sử dụng cơ chế HAL hiện có trong hardware.h để khám phá và tải trình điều khiển. Các đường dẫn ưu tiên cho trình điều khiển Vulkan 32 bit và 64 bit là:

/vendor/lib/hw/vulkan.<ro.hardware.vulkan>.so
/vendor/lib/hw/vulkan.<ro.product.platform>.so
/vendor/lib64/hw/vulkan.<ro.hardware.vulkan>.so
/vendor/lib64/hw/vulkan.<ro.product.platform>.so

Trong Android 7.0 trở lên, phái sinh hw_module_t của Vulkan sẽ gói một cấu trúc hw_module_t duy nhất; chỉ hỗ trợ một trình điều khiển và chuỗi hằng số HWVULKAN_DEVICE_0 được truyền đến open().

Đạo hàm hw_device_t của Vulkan tương ứng với một trình điều khiển có thể hỗ trợ nhiều thiết bị thực. Cấu trúc hw_device_t có thể mở rộng để xuất các hàm vkGetGlobalExtensionProperties(), vkCreateInstance()vkGetInstanceProcAddr(). Trình tải có thể tìm thấy tất cả các hàm VkInstance(), VkPhysicalDevice()vkGetDeviceProcAddr() khác bằng cách gọi vkGetInstanceProcAddr() của cấu trúc hw_device_t.

Khám phá và tải lớp

Trình tải Vulkan hỗ trợ liệt kê và tải các lớp có thể hiển thị các tiện ích bổ sung và chặn các lệnh gọi API cốt lõi trên đường đến trình điều khiển. Android không bao gồm các lớp trên hình ảnh hệ thống; tuy nhiên, các ứng dụng có thể bao gồm các lớp trong tệp APK.

Khi sử dụng các lớp, hãy lưu ý rằng mô hình và chính sách bảo mật của Android khác biệt đáng kể so với các nền tảng khác. Cụ thể, Android không cho phép tải mã bên ngoài vào một quy trình không gỡ lỗi trên các thiết bị phát hành công khai (không bị can thiệp vào hệ thống), cũng như không cho phép mã bên ngoài kiểm tra hoặc kiểm soát bộ nhớ, trạng thái của quy trình, v.v. Điều này bao gồm việc cấm lưu tệp báo lỗi, dấu vết API, v.v. vào ổ đĩa để kiểm tra sau. Chỉ các lớp được phân phối trong ứng dụng không gỡ lỗi mới được bật trên thiết bị chính thức và trình điều khiển không được cung cấp chức năng vi phạm các chính sách này.

Các trường hợp sử dụng lớp bao gồm:

  • Lớp trong thời gian phát triển – Không nên cài đặt lớp xác thực và lớp đệm cho các công cụ theo dõi/phân tích tài nguyên/gỡ lỗi trên hình ảnh hệ thống của thiết bị phát hành chính thức. Các lớp xác thực và shim cho công cụ theo dõi/phân tích tài nguyên/gỡ lỗi phải có thể cập nhật mà không cần hình ảnh hệ thống. Những nhà phát triển muốn sử dụng một trong các lớp này trong quá trình phát triển có thể sửa đổi gói ứng dụng, chẳng hạn như bằng cách thêm tệp vào thư mục thư viện gốc của họ. Các kỹ sư IHV và OEM muốn chẩn đoán lỗi trong quá trình vận chuyển các ứng dụng không thể sửa đổi được giả định là có quyền truy cập vào các bản dựng không phải bản phát hành chính thức (đã bị can thiệp vào hệ thống) của hình ảnh hệ thống, trừ khi các ứng dụng đó có thể gỡ lỗi. Để biết thêm thông tin, hãy xem bài viết Các lớp xác thực Vulkan trên Android.
  • Lớp tiện ích – Các lớp này hiển thị các tiện ích, chẳng hạn như lớp triển khai trình quản lý bộ nhớ cho bộ nhớ thiết bị. Nhà phát triển chọn các lớp và phiên bản của các lớp đó để sử dụng trong ứng dụng của họ; các ứng dụng khác nhau sử dụng cùng một lớp vẫn có thể sử dụng các phiên bản khác nhau. Nhà phát triển chọn lớp nào trong số này để vận chuyển trong gói ứng dụng.
  • Lớp được chèn (ngầm ẩn) – Bao gồm các lớp như tốc độ khung hình, mạng xã hội và lớp phủ trình chạy trò chơi do người dùng hoặc một số ứng dụng khác cung cấp mà ứng dụng không biết hoặc không đồng ý. Các hành vi này vi phạm chính sách bảo mật của Android và không được hỗ trợ.

Đối với các ứng dụng không gỡ lỗi được, trình tải chỉ tìm kiếm các lớp trong thư mục thư viện gốc của ứng dụng và cố gắng tải mọi thư viện có tên khớp với một mẫu cụ thể (ví dụ: libVKLayer_foo.so).

Đối với các ứng dụng có thể gỡ lỗi, trình tải sẽ tìm kiếm các lớp trong /data/local/debug/vulkan và cố gắng tải mọi thư viện khớp với một mẫu cụ thể.

Android cho phép chuyển các lớp cùng với những thay đổi về môi trường tạo bản dựng giữa Android và các nền tảng khác. Để biết thông tin chi tiết về giao diện giữa các lớp và trình tải, hãy xem phần Cấu trúc của giao diện trình tải Vulkan. Các lớp xác thực do Khronos duy trì được lưu trữ trong Lớp xác thực Vulkan.

Các phiên bản và chức năng của API Vulkan

Bảng sau đây liệt kê các phiên bản API Vulkan cho một số bản phát hành Android.
Phiên bản Android Phiên bản Vulkan
Android 13 Vulkan 1.3
Android 9 Vulkan 1.1
Android 7 Vulkan 1.0

Tổng quan về chức năng của Vulkan 1.3

Vulkan 1.3 chuẩn hoá một số tiện ích trước đây không bắt buộc vào chức năng cốt lõi của Vulkan. Phần lớn chức năng này được đưa vào với mục đích tăng cường khả năng kiểm soát và độ chi tiết trên giao diện lập trình Vulkan. Các thực thể truyền kết xuất truyền đơn không cần đối tượng truyền kết xuất hình ảnh hoặc vùng đệm khung nữa. Tổng số đối tượng trạng thái của quy trình có thể giảm và tính năng đồng bộ hoá trong API được cải tiến. Vulkan 1.3 có các yêu cầu về phần cứng tương tự như Vulkan 1.2, 1.1 và 1.0, với hầu hết cách triển khai trong trình điều khiển đồ hoạ dành riêng cho SoC chứ không phải trong khung.

Các tính năng quan trọng nhất của Vulkan 1.3 đối với Android là:

  • Hỗ trợ các thực thể truyền kết xuất một lần
  • Hỗ trợ chấm dứt ngay lệnh gọi chương trình đổ bóng
  • Chi tiết hơn về việc tạo, chia sẻ và kiểm soát quy trình

Vulkan 1.3 cũng bao gồm một số tính năng nhỏ hơn và các tính năng nâng cao khả năng hữu dụng của API. Bạn có thể xem tất cả thay đổi được thực hiện đối với API Vulkan cốt lõi có bản sửa đổi nhỏ 1.3 tại Bản sửa đổi cốt lõi (Vulkan 1.3).

Tổng quan về chức năng của Vulkan 1.2

Vulkan 1.2 bổ sung một số tính năng và tiện ích giúp đơn giản hoá giao diện API. Trong đó bao gồm Mô hình bộ nhớ hợp nhất và thông tin bổ sung có thể truy vấn được qua trình điều khiển thiết bị. Vulkan 1.2 có các yêu cầu về phần cứng giống như Vulkan 1.0 và 1.1; tất cả các hoạt động triển khai đều nằm trong trình điều khiển đồ hoạ dành riêng cho SoC, chứ không phải khung.

Tính năng quan trọng nhất của Vulkan 1.2 dành cho Android là hỗ trợ bộ nhớ 8 bit.

Vulkan 1.2 cũng bao gồm một số tính năng nhỏ hơn và các tính năng nâng cao khả năng hữu dụng của API. Bạn có thể xem tất cả thay đổi đối với API Vulkan cốt lõi có bản sửa đổi nhỏ 1.2 tại Bản sửa đổi cốt lõi (Vulkan 1.2).

Tổng quan về chức năng của Vulkan 1.1

Vulkan 1.1 có tính năng hỗ trợ khả năng tương tác bộ nhớ/đồng bộ hoá, cho phép OEM hỗ trợ Vulkan 1.1 trên thiết bị. Ngoài ra, tính năng tương tác bộ nhớ/đồng bộ hoá cho phép nhà phát triển xác định xem thiết bị có hỗ trợ Vulkan 1.1 hay không và sử dụng hiệu quả khi có. Vulkan 1.1 có các yêu cầu về phần cứng giống như Vulkan 1.0, nhưng hầu hết quá trình triển khai đều nằm trong trình điều khiển đồ hoạ dành riêng cho SOC, chứ không phải trong khung.

Sau đây là các tính năng quan trọng nhất của Vulkan 1.1 dành cho Android:

  • Hỗ trợ nhập và xuất vùng đệm bộ nhớ cũng như đối tượng đồng bộ hoá từ Vulkan bên ngoài (để tương tác với máy ảnh, bộ mã hoá và giải mã và GLES)
  • Hỗ trợ định dạng YCbCr

Vulkan 1.1 cũng bao gồm một số tính năng nhỏ hơn và các tính năng nâng cao khả năng hữu dụng của API. Bạn có thể xem tất cả thay đổi đối với API Vulkan cốt lõi có bản sửa đổi nhỏ 1.1 tại Bản sửa đổi cốt lõi (Vulkan 1.1).

Chọn hỗ trợ Vulkan

Các thiết bị Android phải hỗ trợ bộ tính năng Vulkan tiên tiến nhất hiện có, miễn là các thiết bị đó hỗ trợ ABI 64 bit và có nhiều bộ nhớ.

Các thiết bị chạy Android 13 trở lên phải hỗ trợ Vulkan 1.3.

Các thiết bị chạy qua Android 10 sẽ hỗ trợ Vulkan 1.1.

Các thiết bị khác có thể tuỳ ý hỗ trợ Vulkan 1.3, 1.2 và 1.1.

Hỗ trợ phiên bản Vulkan

Thiết bị Android sẽ hỗ trợ phiên bản Vulkan nếu đáp ứng các điều kiện sau:

  1. Thêm trình điều khiển Vulkan hỗ trợ phiên bản Vulkan mà bạn quan tâm (phải là một trong các phiên bản Vulkan 1.3, 1.1 hoặc 1.0) cùng với các yêu cầu CDD bổ sung của phiên bản Android. Ngoài ra, hãy cập nhật trình điều khiển Vulkan hiện có có số phiên bản Vulkan thấp hơn.
  2. Đối với Vulkan 1.3 hoặc 1.1, hãy đảm bảo rằng tính năng hệ thống do trình quản lý gói trả về sẽ trả về true cho phiên bản vulkan chính xác.
    • Đối với Vulkan 1.3, tính năng này là PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x403000).
    • Đối với Vulkan 1.1, tính năng này là PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x401000).
    Trình quản lý gói sẽ trả về true cho Vulkan 1.3 và Vulkan 1.1 bằng cách thêm một quy tắc (như sau) vào tệp device.mk thích hợp.
    • Thêm nội dung sau cho Vulkan 1.3:
      PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.vulkan.version-1_3.xml:
      $(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml
      
    • Thêm nội dung sau cho Vulkan 1.1:
      PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.vulkan.version-1_1.xml:
      $(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml
      

Hồ sơ cơ sở Android (ABP)

Tất cả thiết bị Android đều nên tuân thủ hồ sơ Android Baseline 2022 mới nhất như đã nêu trong Hướng dẫn về hồ sơ cơ sở Android.

Mọi thiết bị hỗ trợ Android 14 trở lên và API Vulkan đều phải thực hiện tất cả chức năng được xác định trong Hồ sơ cơ sở Android 2021. Danh sách đầy đủ chức năng bắt buộc được liệt kê trong tệp json của hồ sơ Vulkan, nhưng một tập hợp con chính của chức năng bắt buộc bao gồm:

  • Hoạ tiết được nén thông qua ASTC và ETC.
  • Dải màu biến đổi thông qua VK_EXT_swapchain_colorspace.
  • Đổ bóng mẫu và nội suy đa mẫu thông qua sampleRateShading.

Tích hợp hệ thống cửa sổ (WSI)

Trong libvulkan.so, trình điều khiển triển khai các tiện ích tích hợp hệ thống cửa sổ (WSI) sau:

  • VK_KHR_surface
  • VK_KHR_android_surface
  • VK_KHR_swapchain
  • VK_KHR_driver_properties, chỉ được triển khai cho Vulkan 1.1 trong Android 10
  • VK_GOOGLE_display_timing, được triển khai cho mọi phiên bản Vulkan trong Android 10

Các đối tượng VkSurfaceKHRVkSwapchainKHR cũng như mọi hoạt động tương tác với ANativeWindow đều do nền tảng xử lý và không hiển thị với trình điều khiển. Việc triển khai WSI dựa vào tiện ích VK_ANDROID_native_buffer, tiện ích này phải được trình điều khiển hỗ trợ; tiện ích này chỉ được triển khai WSI sử dụng và không hiển thị cho các ứng dụng.

Cờ sử dụng Gralloc

Việc triển khai Vulkan có thể cần phải phân bổ vùng đệm chuỗi hoán đổi bằng cờ sử dụng Gralloc riêng tư do quá trình triển khai xác định. Khi tạo một chuỗi hoán đổi, Android yêu cầu trình điều khiển dịch cờ sử dụng hình ảnh và định dạng được yêu cầu thành cờ sử dụng Gralloc bằng cách gọi:

typedef enum VkSwapchainImageUsageFlagBitsANDROID {
    VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID = 0x00000001,
    VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkSwapchainImageUsageFlagBitsANDROID;
typedef VkFlags VkSwapchainImageUsageFlagsANDROID;

VkResult VKAPI vkGetSwapchainGrallocUsage2ANDROID(
    VkDevice                          device,
    VkFormat                          format,
    VkImageUsageFlags                 imageUsage,
    VkSwapchainImageUsageFlagsANDROID swapchainUsage,
    uint64_t*                         grallocConsumerUsage,
    uint64_t*                         grallocProducerUsage
);

Tham số formatimageUsage được lấy từ cấu trúc VkSwapchainCreateInfoKHR. Trình điều khiển sẽ điền *grallocConsumerUsage*grallocProducerUsage bằng các cờ sử dụng Gralloc bắt buộc cho định dạng và cách sử dụng. Cờ sử dụng do trình điều khiển trả về được kết hợp với cờ sử dụng mà thực thể tiêu thụ trong chuỗi hoán đổi yêu cầu khi phân bổ vùng đệm.

Android 7.x gọi một phiên bản VkSwapchainImageUsageFlagsANDROID() cũ hơn, tên là vkGetSwapchainGrallocUsageANDROID(). Android 8.0 trở lên không dùng vkGetSwapchainGrallocUsageANDROID() nữa nhưng vẫn gọi vkGetSwapchainGrallocUsageANDROID() nếu trình điều khiển không cung cấp vkGetSwapchainGrallocUsage2ANDROID():

VkResult VKAPI vkGetSwapchainGrallocUsageANDROID(
    VkDevice            device,
    VkFormat            format,
    VkImageUsageFlags   imageUsage,
    int*                grallocUsage
);

vkGetSwapchainGrallocUsageANDROID() không hỗ trợ cờ sử dụng chuỗi hoán đổi hoặc cờ sử dụng Gralloc mở rộng.

Hình ảnh được Gralloc hỗ trợ

VkNativeBufferANDROID là cấu trúc tiện ích vkCreateImage để tạo hình ảnh được hỗ trợ bởi vùng đệm Gralloc. VkNativeBufferANDROID được cung cấp cho vkCreateImage() trong chuỗi cấu trúc VkImageCreateInfo. Các lệnh gọi đến vkCreateImage() với VkNativeBufferANDROID xảy ra trong lệnh gọi đến vkCreateSwapchainKHR. Việc triển khai WSI sẽ phân bổ số lượng bộ đệm gốc được yêu cầu cho chuỗi hoán đổi, sau đó tạo một VkImage cho mỗi bộ đệm:

typedef struct {
    VkStructureType             sType; // must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
    const void*                 pNext;

    // Buffer handle and stride returned from gralloc alloc()
    buffer_handle_t             handle;
    int                         stride;

    // Gralloc format and usage requested when the buffer was allocated.
    int                         format;
    int                         usage;
    // Beginning in Android 8.0, the usage field above is deprecated and the
    // usage2 struct below was added. The usage field is still filled in for
    // compatibility with Android 7.0 drivers. Drivers for Android 8.0
    // should prefer the usage2 struct, especially if the
    // android.hardware.graphics.allocator HAL uses the extended usage bits.
    struct {
        uint64_t                consumer;
        uint64_t                producer;
    } usage2;
} VkNativeBufferANDROID;

Khi tạo hình ảnh được Gralloc hỗ trợ, VkImageCreateInfo có các dữ liệu sau:

  .sType               = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
  .pNext               = the above VkNativeBufferANDROID structure
  .imageType           = VK_IMAGE_TYPE_2D
  .format              = a VkFormat matching the format requested for the gralloc buffer
  .extent              = the 2D dimensions requested for the gralloc buffer
  .mipLevels           = 1
  .arraySize           = 1
  .samples             = 1
  .tiling              = VK_IMAGE_TILING_OPTIMAL
  .usage               = VkSwapchainCreateInfoKHR::imageUsage
  .flags               = 0
  .sharingMode         = VkSwapchainCreateInfoKHR::imageSharingMode
  .queueFamilyCount    = VkSwapchainCreateInfoKHR::queueFamilyIndexCount
  .pQueueFamilyIndices = VkSwapchainCreateInfoKHR::pQueueFamilyIndices

Trong Android 8.0 trở lên, nền tảng này cung cấp cấu trúc mở rộng VkSwapchainImageCreateInfoKHR trong chuỗi VkImageCreateInfo được cung cấp cho vkCreateImage khi cần bất kỳ cờ sử dụng hình ảnh chuỗi hoán đổi nào cho chuỗi hoán đổi. Cấu trúc mở rộng chứa các cờ sử dụng hình ảnh chuỗi hoán đổi:

typedef struct {
    VkStructureType                        sType; // must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID
    const void*                            pNext;

    VkSwapchainImageUsageFlagsANDROID      usage;
} VkSwapchainImageCreateInfoANDROID;

Trong Android 10 trở lên, nền tảng này hỗ trợ VK_KHR_swapchain phiên bản 70, vì vậy, ứng dụng Vulkan có thể tạo VkImage được hỗ trợ bởi bộ nhớ chuỗi hoán đổi. Trước tiên, ứng dụng gọi vkCreateImage bằng cấu trúc VkImageSwapchainCreateInfoKHR được liên kết với cấu trúc VkImageCreateInfo. Sau đó, ứng dụng sẽ gọi vkBindImageMemory2(KHR) bằng cấu trúc VkBindImageMemorySwapchainInfoKHR được nối với cấu trúc VkBindImageMemoryInfo. imageIndex được chỉ định trong cấu trúc VkBindImageMemorySwapchainInfoKHR phải là chỉ mục hình ảnh chuỗi hoán đổi hợp lệ. Trong khi đó, nền tảng cung cấp một cấu trúc tiện ích VkNativeBufferANDROID với thông tin vùng đệm Gralloc tương ứng cho chuỗi VkBindImageMemoryInfo, nhờ đó, trình điều khiển biết vùng đệm Gralloc nào sẽ liên kết với VkImage.

Thu thập hình ảnh

vkAcquireImageANDROID mua quyền sở hữu hình ảnh chuỗi hoán đổi và nhập hàng rào gốc được báo hiệu bên ngoài vào cả đối tượng VkSemaphore hiện có và đối tượng VkFence hiện có:

VkResult VKAPI vkAcquireImageANDROID(
    VkDevice            device,
    VkImage             image,
    int                 nativeFenceFd,
    VkSemaphore         semaphore,
    VkFence             fence
);

vkAcquireImageANDROID() được gọi trong vkAcquireNextImageKHR để nhập hàng rào gốc vào các đối tượng VkSemaphoreVkFence do ứng dụng cung cấp (tuy nhiên, cả đối tượng semaphore và hàng rào đều không bắt buộc trong lệnh gọi này). Trình điều khiển cũng có thể sử dụng cơ hội này để nhận dạng và xử lý mọi thay đổi bên ngoài đối với trạng thái vùng đệm Gralloc; nhiều trình điều khiển sẽ không cần làm gì ở đây. Lệnh gọi này đặt VkSemaphoreVkFence vào cùng một trạng thái đang chờ xử lý như thể được vkQueueSubmit báo hiệu, vì vậy, các hàng đợi có thể chờ trên semaphore và ứng dụng có thể chờ trên hàng rào.

Cả hai đối tượng đều được báo hiệu khi hàng rào gốc cơ bản báo hiệu; nếu hàng rào gốc đã báo hiệu, thì semaphore sẽ ở trạng thái báo hiệu khi hàm này trả về. Trình điều khiển sẽ sở hữu chỉ số mô tả tệp hàng rào và đóng chỉ số mô tả tệp hàng rào khi không cần thiết nữa. Trình điều khiển phải làm như vậy ngay cả khi không cung cấp đối tượng semaphore hoặc hàng rào, hoặc ngay cả khi vkAcquireImageANDROID không thành công và trả về lỗi. Nếu fenceFd là -1, thì có vẻ như hàng rào gốc đã được báo hiệu.

Hình ảnh phát hành

vkQueueSignalReleaseImageANDROID chuẩn bị hình ảnh chuỗi hoán đổi để sử dụng bên ngoài, tạo một hàng rào gốc và lên lịch phát tín hiệu hàng rào gốc sau khi các semaphore đầu vào đã báo hiệu:

VkResult VKAPI vkQueueSignalReleaseImageANDROID(
    VkQueue             queue,
    uint32_t            waitSemaphoreCount,
    const VkSemaphore*  pWaitSemaphores,
    VkImage             image,
    int*                pNativeFenceFd
);

vkQueuePresentKHR() gọi vkQueueSignalReleaseImageANDROID() trên hàng đợi được cung cấp. Trình điều khiển phải tạo một hàng rào gốc không báo hiệu cho đến khi tất cả các semaphore waitSemaphoreCount trong tín hiệu pWaitSemaphores và mọi công việc cần thiết khác để chuẩn bị image cho việc trình bày hoàn tất.

Nếu các semaphore chờ (nếu có) đã được báo hiệu và queue đang ở trạng thái rảnh, trình điều khiển có thể đặt *pNativeFenceFd thành -1 thay vì chỉ số mô tả tệp hàng rào gốc thực tế, cho biết rằng không có gì để chờ. Phương thức gọi sở hữu và đóng chỉ số mô tả tệp được trả về trong *pNativeFenceFd.

Nhiều trình điều khiển có thể bỏ qua tham số hình ảnh, nhưng một số trình điều khiển có thể cần chuẩn bị cấu trúc dữ liệu phía CPU liên kết với vùng đệm Gralloc để người dùng hình ảnh bên ngoài sử dụng. Bạn nên chuẩn bị nội dung vùng đệm để người dùng bên ngoài sử dụng một cách không đồng bộ trong quá trình chuyển đổi hình ảnh sang VK_IMAGE_LAYOUT_PRESENT_SRC_KHR.

Nếu hình ảnh được tạo bằng VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID, thì trình điều khiển phải cho phép gọi vkQueueSignalReleaseImageANDROID() nhiều lần mà không can thiệp vào các lệnh gọi đến vkAcquireImageANDROID().

Hỗ trợ hình ảnh có thể hiển thị được chia sẻ

Một số thiết bị có thể chia sẻ quyền sở hữu một hình ảnh giữa quy trình hiển thị và quá trình triển khai Vulkan để giảm thiểu độ trễ. Trên Android 9 trở lên, trình tải quảng cáo có điều kiện tiện ích VK_KHR_shared_presentable_image dựa trên phản hồi của trình điều khiển đối với lệnh gọi đến vkGetPhysicalDeviceProperties2.

Nếu trình điều khiển không hỗ trợ Vulkan 1.1 hoặc tiện ích VK_KHR_physical_device_properties2, thì trình tải sẽ không quảng cáo hỗ trợ cho các hình ảnh có thể trình bày được chia sẻ. Nếu không, trình tải sẽ truy vấn các chức năng của trình điều khiển bằng cách gọi vkGetPhysicalDeviceProperties2() và đưa cấu trúc sau vào chuỗi VkPhysicalDeviceProperties2::pNext:

typedef struct {
    VkStructureType sType; // must be VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID
    const void*     pNext;
    VkBool32        sharedImage;
} VkPhysicalDevicePresentationPropertiesANDROID;

Nếu trình điều khiển có thể chia sẻ quyền sở hữu hình ảnh với hệ thống hiển thị, thì trình điều khiển sẽ đặt thành phần sharedImage thành VK_TRUE.

Xác nhận kết quả

Nhà sản xuất thiết bị gốc (OEM) có thể kiểm thử việc triển khai Vulkan bằng CTS, bao gồm:

  • Kiểm thử tuân thủ Khronos Vulkan trong mô-đun CtsDeqpTestCases, bao gồm các kiểm thử API chức năng cho Vulkan 1.0, 1.1, 1.2 và 1.3.
  • Mô-đun CtsGraphicsTestCases kiểm tra để đảm bảo thiết bị được định cấu hình chính xác cho các chức năng Vulkan mà thiết bị hỗ trợ.

Cờ tính năng Vulkan

Thiết bị phải hỗ trợ Android 11 trở lên và hỗ trợ API Vulkan để hiển thị cờ tính năng android.software.vulkan.deqp.level. Giá trị của cờ tính năng này là một ngày, được mã hoá dưới dạng giá trị số nguyên. Thuộc tính này chỉ định ngày liên kết với các bài kiểm thử dEQP Vulkan mà thiết bị tuyên bố đã vượt qua.

Ngày có dạng YYYY-MM-DD được mã hoá thành số nguyên 32 bit như sau:

  • Các bit từ 0 đến 15 lưu trữ năm
  • Các bit 16-23 lưu trữ tháng
  • Bit 24-31 lưu trữ trong ngày

Giá trị tối thiểu được phép cho cờ tính năng là 0x07E30301, tương ứng với ngày 01-03-2019. Đây là ngày được liên kết với các bài kiểm thử dEQP Vulkan cho Android 10. Nếu cờ tính năng có giá trị tối thiểu là giá trị này, thì thiết bị sẽ tuyên bố đã vượt qua tất cả các bài kiểm thử dEQP Vulkan trên Android 10.

Giá trị 0x07E40301 tương ứng với ngày 01/03/2020, là ngày liên kết với các thử nghiệm dEQP Vulkan cho Android 11. Nếu cờ tính năng có ít nhất là giá trị này, thì thiết bị tuyên bố là vượt qua tất cả các bài kiểm thử dEQP của Android 11.

Giá trị 0x07E60301 tương ứng với ngày 01/03/2022, là ngày liên kết với các thử nghiệm dEQP Vulkan cho Android 13. Nếu cờ tính năng có giá trị tối thiểu là giá trị này, thì thiết bị sẽ tuyên bố đã vượt qua tất cả các bài kiểm thử dEQP Vulkan trên Android 13.

Một thiết bị hiển thị một cờ tính năng cụ thể (tức là 0x07E30301, 0x07E40301, 0x07E60301) tuyên bố đã vượt qua tất cả các thử nghiệm dEQP của Android Vulkan của cờ tính năng đó (Android 10, Android 11, Android 13 tương ứng). Thiết bị này có thể vượt qua các bài kiểm thử dEQP Vulkan từ một bản phát hành Android sau này.

Vulkan dEQP là một phần của Android CTS. Kể từ Android 11, thành phần trình chạy kiểm thử dEQP của CTS sẽ nhận biết được cờ tính năng android.software.vulkan.deqp.level và bỏ qua mọi kiểm thử dEQP Vulkan mà theo cờ tính năng này, thiết bị không tuyên bố hỗ trợ. Các chương trình kiểm thử như vậy được báo cáo là vượt qua một cách dễ dàng.