ใช้งาน Vulkan

Vulkan เป็น API แบบข้ามแพลตฟอร์มที่มีค่าใช้จ่ายต่ำสำหรับกราฟิก 3 มิติที่มีประสิทธิภาพสูง Vulkan มีเครื่องมือสำหรับสร้างกราฟิกคุณภาพสูงแบบเรียลไทม์ในแอปเช่นเดียวกับ OpenGL ES (GLES) ข้อดีของการใช้ Vulkan ได้แก่ การลดค่าใช้จ่ายส่วนเกินของ CPU และการรองรับภาษาSPIR-V Binary Intermediate

อุปกรณ์ต้องมีสิ่งต่อไปนี้จึงจะใช้ Vulkan ได้สําเร็จ

  • โปรแกรมโหลด Vulkan ที่ Android มีให้
  • โปรแกรมควบคุม Vulkan ที่ SoC เช่น IHV ของ GPU ให้มา ซึ่งใช้ Vulkan API อุปกรณ์ Android ต้องมีฮาร์ดแวร์ GPU ที่รองรับ Vulkan และไดรเวอร์ที่เกี่ยวข้องจึงจะรองรับฟังก์ชันการทำงานของ Vulkan ได้ GPU ต้องรองรับ GLES 3.1 ขึ้นไปด้วย โปรดปรึกษาตัวแทนจำหน่าย SoC เพื่อขอการสนับสนุนเกี่ยวกับไดรเวอร์

หากอุปกรณ์มีไดรเวอร์ Vulkan อุปกรณ์จะต้องประกาศฟีเจอร์ระบบ FEATURE_VULKAN_HARDWARE_LEVEL และ FEATURE_VULKAN_HARDWARE_VERSION พร้อมเวอร์ชันที่แสดงถึงความสามารถของอุปกรณ์อย่างถูกต้อง ซึ่งจะช่วยให้มั่นใจว่าอุปกรณ์เป็นไปตามเอกสารนิยามความเข้ากันได้ (CDD)

โปรแกรมโหลด Vulkan

โปรแกรมโหลด Vulkan platform/frameworks/native/vulkan เป็นอินเทอร์เฟซหลักระหว่างแอป Vulkan กับไดรเวอร์ Vulkan ของอุปกรณ์ ระบบจะติดตั้งตัวโหลด Vulkan ที่ /system/lib[64]/libvulkan.so ตัวโหลดจะมีจุดแรกเข้า Vulkan API หลัก จุดแรกเข้าของส่วนขยายที่ Android CDD ต้องการ และส่วนขยายที่ไม่บังคับเพิ่มเติมอีกมากมาย ส่วนขยายการผสานรวมระบบ (WSI) ของ Windows จะส่งออกโดยโปรแกรมโหลดและติดตั้งใช้งานในโปรแกรมโหลดเป็นหลัก ไม่ใช่ในไดรเวอร์ นอกจากนี้ โปรแกรมโหลดยังรองรับการระบุรายการและโหลดเลเยอร์ที่สามารถแสดงส่วนขยายเพิ่มเติมและขัดจังหวะการเรียก API หลักระหว่างทางไปยังไดรเวอร์

NDK มีไลบรารี libvulkan.so จำลองสําหรับการลิงก์ ไลบรารีจะส่งออกสัญลักษณ์เดียวกับตัวโหลด แอปเรียกใช้ฟังก์ชันที่ส่งออกจากไลบรารี libvulkan.so จริงเพื่อป้อนฟังก์ชันแทรมโพลีนในตัวโหลด ซึ่งจะส่งข้อมูลไปยังเลเยอร์หรือไดรเวอร์ที่เหมาะสมตามอาร์กิวเมนต์แรก vkGet*ProcAddr() call จะแสดงผลตัวชี้ฟังก์ชันที่ส่งผ่านไปยังแทรมโปลีน (กล่าวคือ เรียกใช้โค้ด API หลักโดยตรง) การเรียกผ่านตัวชี้ฟังก์ชันแทนสัญลักษณ์ที่ส่งออกจะมีประสิทธิภาพมากกว่าเนื่องจากจะข้ามแทรมโปลีนและการส่ง

การแจกแจงและการโหลดไดรเวอร์

เมื่อสร้างอิมเมจระบบแล้ว Android คาดหวังว่าระบบจะทราบว่า GPU ใดพร้อมใช้งาน ตัวโหลดใช้กลไก HAL ที่มีอยู่ใน hardware.h เพื่อค้นหาและโหลดไดรเวอร์ เส้นทางที่แนะนำสำหรับไดรเวอร์ Vulkan แบบ 32 บิตและ 64 บิตมีดังนี้

/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

ใน Android 7.0 ขึ้นไป อนุพันธ์ hw_module_t ของ Vulkan จะรวมโครงสร้าง hw_module_t รายการเดียว รองรับไดรเวอร์เพียงรายการเดียว และส่งสตริงค่าคงที่ HWVULKAN_DEVICE_0 ไปยัง open()

อนุพันธ์ hw_device_t ของ Vulkan สอดคล้องกับไดรเวอร์เดียวที่รองรับอุปกรณ์จริงหลายเครื่อง โครงสร้าง hw_device_t สามารถขยายเพื่อส่งออกฟังก์ชัน vkGetGlobalExtensionProperties(), vkCreateInstance() และ vkGetInstanceProcAddr() โปรแกรมโหลดจะค้นหาฟังก์ชัน VkInstance(), VkPhysicalDevice() และ vkGetDeviceProcAddr() อื่นๆ ทั้งหมดได้โดยเรียกใช้ vkGetInstanceProcAddr() ของโครงสร้าง hw_device_t

การค้นพบและการโหลดเลเยอร์

โปรแกรมโหลด Vulkan รองรับการแจกแจงรายการและโหลดเลเยอร์ที่สามารถแสดงส่วนขยายเพิ่มเติมและขัดจังหวะการเรียก API หลักระหว่างทางไปยังไดรเวอร์ Android จะไม่รวมเลเยอร์ไว้ในภาพระบบ แต่แอปอาจรวมเลเยอร์ไว้ใน APK

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

กรณีการใช้งานเลเยอร์มีดังนี้

  • เลเยอร์สำหรับช่วงการพัฒนา - ไม่ควรติดตั้งเลเยอร์การตรวจสอบและชิมสำหรับเครื่องมือการติดตาม/การโปรไฟล์/การแก้ไขข้อบกพร่องในอิมเมจระบบของอุปกรณ์เวอร์ชันที่ใช้งานจริง เลเยอร์การตรวจสอบและชิมสำหรับเครื่องมือการติดตาม/การโปรไฟล์/การแก้ไขข้อบกพร่องควรอัปเดตได้โดยไม่ต้องมีภาพระบบ นักพัฒนาแอปที่ต้องการใช้เลเยอร์เหล่านี้ระหว่างการพัฒนาสามารถแก้ไขแพ็กเกจแอปได้ เช่น โดยการเพิ่มไฟล์ลงในไดเรกทอรีไลบรารีเนทีฟ ระบบจะถือว่าวิศวกร IHV และ OEM ที่ต้องการวินิจฉัยข้อผิดพลาดในการเผยแพร่แอปที่แก้ไขไม่ได้มีสิทธิ์เข้าถึงบิลด์ที่ไม่ใช่เวอร์ชันที่ใช้งานจริง (รูท) ของภาพระบบ เว้นแต่แอปเหล่านั้นจะแก้ไขข้อบกพร่องได้ ดูข้อมูลเพิ่มเติมได้ที่เลเยอร์การตรวจสอบ Vulkan ใน Android
  • เลเยอร์ยูทิลิตี — เลเยอร์เหล่านี้จะแสดงส่วนขยาย เช่น เลเยอร์ที่ใช้ตัวจัดการหน่วยความจําสําหรับหน่วยความจําของอุปกรณ์ นักพัฒนาแอปเลือกเลเยอร์และเวอร์ชันของเลเยอร์เหล่านั้นเพื่อใช้ในแอปของตน โดยแอปต่างๆ ที่ใช้เลเยอร์เดียวกันอาจยังคงใช้เวอร์ชันที่แตกต่างกัน นักพัฒนาแอปเลือกเลเยอร์ที่จะรวมไว้ในแพ็กเกจแอปได้
  • เลเยอร์ที่แทรก (โดยนัย) — รวมถึงเลเยอร์ต่างๆ เช่น อัตราเฟรม โซเชียลเน็ตเวิร์ก และการวางซ้อนของโปรแกรมเปิดเกมที่ผู้ใช้หรือแอปอื่นระบุไว้โดยที่แอปไม่รู้หรือไม่ได้ให้ความยินยอม ซึ่งละเมิดนโยบายความปลอดภัยของ Android และไม่รองรับ

สำหรับแอปที่แก้ไขข้อบกพร่องไม่ได้ ตัวโหลดจะค้นหาเลเยอร์เฉพาะในไดเรกทอรีไลบรารีเนทีฟของแอปและจะพยายามโหลดไลบรารีที่มีชื่อตรงกับรูปแบบหนึ่งๆ (เช่น libVKLayer_foo.so)

สําหรับแอปที่แก้ไขข้อบกพร่องได้ โปรแกรมโหลดจะค้นหาเลเยอร์ใน/data/local/debug/vulkan และพยายามโหลดไลบรารีที่ตรงกับรูปแบบหนึ่งๆ

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

เวอร์ชันและความสามารถของ Vulkan API

ตารางต่อไปนี้แสดงเวอร์ชัน Vulkan API สำหรับ Android หลายรุ่น
รุ่นของ Android เวอร์ชัน Vulkan
Android 13 Vulkan 1.3
Android 9 Vulkan 1.1
Android 7 Vulkan 1.0

ภาพรวมฟังก์ชันการทำงานของ Vulkan 1.3

Vulkan 1.3 กำหนดส่วนขยายที่ไม่บังคับจำนวนหนึ่งก่อนหน้านี้ให้เป็นฟังก์ชันหลักของ Vulkan ฟังก์ชันการทํางานส่วนใหญ่นี้มีไว้เพื่อเพิ่มการควบคุมและความละเอียดของอินเทอร์เฟซการเขียนโปรแกรม Vulkan อินสแตนซ์ของพาสการแสดงผลแบบผ่านครั้งเดียวไม่จําเป็นต้องใช้ออบเจ็กต์พาสการแสดงผลหรือเฟรมบัฟเฟอร์อีกต่อไป จำนวนออบเจ็กต์สถานะไปป์ไลน์ทั้งหมดจะลดลง และมีการปรับปรุงการซิงค์ภายใน API Vulkan 1.3 มีข้อกำหนดด้านฮาร์ดแวร์เหมือนกับ Vulkan 1.2, 1.1 และ 1.0 โดยมีการใช้งานส่วนใหญ่ในโปรแกรมควบคุมกราฟิกสำหรับ SoC โดยเฉพาะ ไม่ใช่ในเฟรมเวิร์ก

ฟีเจอร์ที่สำคัญที่สุดของ Vulkan 1.3 สำหรับ Android มีดังนี้

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

นอกจากนี้ Vulkan 1.3 ยังมีฟีเจอร์เล็กๆ น้อยๆ และการเพิ่มประสิทธิภาพการทํางานของ API การเปลี่ยนแปลงทั้งหมดที่ทำกับ Vulkan API หลักที่มีการแก้ไขย่อย 1.3 จะอยู่ที่การแก้ไขหลัก (Vulkan 1.3)

ภาพรวมฟังก์ชันการทำงานของ Vulkan 1.2

Vulkan 1.2 เพิ่มฟีเจอร์และส่วนขยายหลายรายการที่ลดความซับซ้อนของอินเทอร์เฟซ API ซึ่งรวมถึงโมเดลหน่วยความจำแบบรวมและข้อมูลเพิ่มเติมที่ค้นหาได้จากไดรเวอร์อุปกรณ์ Vulkan 1.2 มีข้อกำหนดด้านฮาร์ดแวร์เหมือนกับ Vulkan 1.0 และ 1.1 การใช้งานทั้งหมดอยู่ในโปรแกรมควบคุมกราฟิกที่เจาะจง SoC ไม่ใช่เฟรมเวิร์ก

ฟีเจอร์ที่สำคัญที่สุดของ Vulkan 1.2 สำหรับ Android คือการรองรับพื้นที่เก็บข้อมูล 8 บิต

นอกจากนี้ Vulkan 1.2 ยังมีฟีเจอร์เล็กๆ น้อยๆ และการเพิ่มประสิทธิภาพการทํางานของ API ด้วย ดูการเปลี่ยนแปลงทั้งหมดที่เกิดขึ้นกับ Vulkan API หลักที่มีการปรับแก้เล็กน้อย 1.2 ได้ที่การปรับแก้หลัก (Vulkan 1.2)

ภาพรวมฟังก์ชันการทำงานของ Vulkan 1.1

Vulkan 1.1 รองรับการทำงานร่วมกันของหน่วยความจำ/การซิงค์ ซึ่งช่วยให้ OEM รองรับ Vulkan 1.1 ในอุปกรณ์ได้ นอกจากนี้ การทํางานร่วมกันของหน่วยความจํา/การซิงค์ยังช่วยให้นักพัฒนาแอปตรวจสอบได้ว่าอุปกรณ์รองรับ Vulkan 1.1 หรือไม่ และใช้งานอย่างมีประสิทธิภาพเมื่อรองรับ Vulkan 1.1 Vulkan 1.1 มีข้อกําหนดด้านฮาร์ดแวร์เหมือนกับ Vulkan 1.0 แต่การใช้งานส่วนใหญ่อยู่ในโปรแกรมควบคุมกราฟิกเฉพาะ SOC ไม่ใช่ในเฟรมเวิร์ก

ฟีเจอร์ที่สำคัญที่สุดของ Vulkan 1.1 สำหรับ Android มีดังนี้

  • รองรับการนําเข้าและส่งออกบัฟเฟอร์หน่วยความจําและออบเจ็กต์การซิงค์จากภายนอก Vulkan (สําหรับการทํางานร่วมกันกับกล้อง โค้ดคิว และ GLES)
  • การรองรับรูปแบบ YCbCr

นอกจากนี้ Vulkan 1.1 ยังมีฟีเจอร์เล็กๆ น้อยๆ และการเพิ่มประสิทธิภาพการทํางานของ API ด้วย ดูการเปลี่ยนแปลงทั้งหมดที่ทำกับ Vulkan API หลักที่มีการปรับแก้เล็กน้อย 1.1 ได้ที่การปรับแก้หลัก (Vulkan 1.1)

เลือกการสนับสนุน Vulkan

อุปกรณ์ Android ควรรองรับชุดฟีเจอร์ Vulkan ที่ทันสมัยที่สุดเท่าที่มีให้ใช้งาน ในกรณีที่รองรับ ABI 64 บิตและหน่วยความจำไม่ต่ำ

อุปกรณ์ที่เปิดตัวด้วย Android 13 ขึ้นไปควรรองรับ Vulkan 1.3

อุปกรณ์ที่เปิดตัวผ่าน Android 10 ควรรองรับ Vulkan 1.1

อุปกรณ์อื่นๆ อาจรองรับ Vulkan 1.3, 1.2 และ 1.1

รองรับเวอร์ชัน Vulkan

อุปกรณ์ Android จะรองรับ Vulkan เวอร์ชันหนึ่งๆ ได้หากเป็นไปตามเงื่อนไขต่อไปนี้

  1. เพิ่มไดรเวอร์ Vulkan ที่รองรับเวอร์ชัน Vulkan ที่ต้องการ (ต้องเป็นเวอร์ชัน Vulkan 1.3, 1.1 หรือ 1.0) ควบคู่ไปกับข้อกำหนด CDD เพิ่มเติมของเวอร์ชัน Android หรือจะอัปเดตไดรเวอร์ Vulkan ที่มีอยู่ซึ่งมีหมายเลขเวอร์ชันต่ำกว่าก็ได้
  2. สำหรับ Vulkan 1.3 หรือ 1.1 โปรดตรวจสอบว่าฟีเจอร์ของระบบที่ตัวจัดการแพ็กเกจแสดงผล true สำหรับเวอร์ชัน Vulkan ที่ถูกต้อง
    • สำหรับ Vulkan 1.3 ฟีเจอร์นี้จะเป็น PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x403000)
    • สำหรับ Vulkan 1.1 ฟีเจอร์คือ PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x401000)
    เครื่องมือจัดการแพ็กเกจจะแสดงผล true สำหรับ Vulkan 1.3 และ Vulkan 1.1 ด้วยการเพิ่มกฎดังที่แสดงไว้ด้านล่างลงในไฟล์ device.mk ที่เหมาะสม
    • เพิ่มข้อมูลต่อไปนี้สำหรับ 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
      
    • เพิ่มข้อมูลต่อไปนี้สำหรับ 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
      

โปรไฟล์พื้นฐานของ Android (ABP)

เราขอแนะนำให้อุปกรณ์ Android ทั้งหมดเป็นไปตามโปรไฟล์ Android Baseline 2022 เวอร์ชันล่าสุดตามที่ระบุไว้ในคู่มือโปรไฟล์ Android Baseline

อุปกรณ์ที่รองรับ Android 14 ขึ้นไปและ Vulkan API ต้องมีฟังก์ชันการทำงานทั้งหมดตามที่ระบุไว้ในโปรไฟล์ Android Baseline 2021 มีการระบุรายการฟังก์ชันการทำงานที่จำเป็นทั้งหมดในไฟล์ json ของโปรไฟล์ Vulkan แต่ชุดย่อยที่สำคัญของฟังก์ชันการทำงานที่จำเป็นมีดังนี้

  • พื้นผิวที่บีบอัดผ่าน ASTC และ ETC
  • พื้นที่สีแบบตัวแปรผ่าน VK_EXT_swapchain_colorspace
  • ตัวอย่างการแรเงาและการปักหมุดหลายตัวอย่างผ่าน sampleRateShading

การผสานรวมระบบหน้าต่าง (WSI)

ใน libvulkan.so ไดรเวอร์จะใช้ส่วนขยายการผสานรวมระบบหน้าต่าง (WSI) ต่อไปนี้

  • VK_KHR_surface
  • VK_KHR_android_surface
  • VK_KHR_swapchain
  • VK_KHR_driver_properties ใช้งานกับ Vulkan 1.1 ใน Android 10 เท่านั้น
  • VK_GOOGLE_display_timing ที่ใช้งานกับ Vulkan ทุกเวอร์ชันใน Android 10

ออบเจ็กต์ VkSurfaceKHR และ VkSwapchainKHR รวมถึงการโต้ตอบทั้งหมดกับ ANativeWindow จะได้รับการจัดการโดยแพลตฟอร์มและจะไม่แสดงให้ผู้ขับขี่เห็น การติดตั้งใช้งาน WSI ต้องใช้ส่วนขยาย VK_ANDROID_native_buffer ซึ่งไดรเวอร์ต้องรองรับ ส่วนขยายนี้ใช้โดยการติดตั้งใช้งาน WSI เท่านั้นและจะไม่แสดงต่อแอป

Flag การใช้งาน Gralloc

การใช้งาน Vulkan อาจต้องมีการจัดสรรบัฟเฟอร์ Swapchain ด้วย Flag การใช้งาน Gralloc ส่วนตัวที่กําหนดโดยการใช้งาน เมื่อสร้าง Swapchain Android จะขอให้ไดรเวอร์แปลงรูปแบบและ Flag การใช้งานรูปภาพที่ขอเป็น Flag การใช้งาน Gralloc โดยการเรียกใช้

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

พารามิเตอร์ format และ imageUsage ดึงมาจากโครงสร้าง VkSwapchainCreateInfoKHR ไดรเวอร์ควรกรอก *grallocConsumerUsage และ *grallocProducerUsage ด้วยแฟล็กการใช้งาน Gralloc ที่จำเป็นสำหรับรูปแบบและการใช้งาน แฟล็กการใช้งานที่แสดงผลโดยไดรเวอร์จะรวมกับแฟล็กการใช้งานที่ผู้บริโภคการสลับเชนขอเมื่อจัดสรรบัฟเฟอร์

Android 7.x เรียกใช้ VkSwapchainImageUsageFlagsANDROID() เวอร์ชันก่อนหน้าชื่อ vkGetSwapchainGrallocUsageANDROID() Android 8.0 ขึ้นไปเลิกใช้งาน vkGetSwapchainGrallocUsageANDROID() แต่ยังคงเรียกใช้ vkGetSwapchainGrallocUsageANDROID() หาก vkGetSwapchainGrallocUsage2ANDROID()ไม่ได้มาจากไดรเวอร์

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

vkGetSwapchainGrallocUsageANDROID() ไม่รองรับ Flag การใช้งาน Swapchain หรือ Flag การใช้งาน Gralloc แบบขยาย

รูปภาพจาก Gralloc

VkNativeBufferANDROID คือโครงสร้างส่วนขยาย vkCreateImage สำหรับการสร้างรูปภาพที่สำรองข้อมูลโดยบัฟเฟอร์ Gralloc VkNativeBufferANDROID มีการระบุให้กับ vkCreateImage() ในเชนโครงสร้าง VkImageCreateInfo การโทรหา vkCreateImage() จาก VkNativeBufferANDROID เกิดขึ้นขณะโทรหา vkCreateSwapchainKHR การใช้งาน WSI จะจัดสรรจำนวนบัฟเฟอร์เนทีฟที่ขอสำหรับสวิตช์เชน จากนั้นจะสร้างVkImageสำหรับแต่ละรายการ ดังนี้

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;

เมื่อสร้างรูปภาพที่อิงกับ Gralloc VkImageCreateInfo จะมีข้อมูลต่อไปนี้

  .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

ใน Android 8.0 ขึ้นไป แพลตฟอร์มจะมีโครงสร้างส่วนขยาย VkSwapchainImageCreateInfoKHR ในเชน VkImageCreateInfo ที่มีไว้สำหรับ vkCreateImage เมื่อต้องมีแฟล็กการใช้งานอิมเมจ Swapchain โครงสร้างส่วนขยายมีแฟล็กการใช้งานอิมเมจ Swapchain ดังนี้

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

    VkSwapchainImageUsageFlagsANDROID      usage;
} VkSwapchainImageCreateInfoANDROID;

ใน Android 10 ขึ้นไป แพลตฟอร์มจะรองรับ VK_KHR_swapchain v70 แอป Vulkan จึงสามารถสร้าง VkImage ที่หน่วยความจำ Swapchain รองรับ แอปเรียกใช้ vkCreateImage ก่อน โดยมีโครงสร้าง VkImageSwapchainCreateInfoKHR ที่เชื่อมโยงกับโครงสร้าง VkImageCreateInfo จากนั้นแอปเรียกใช้ vkBindImageMemory2(KHR) ด้วยโครงสร้าง VkBindImageMemorySwapchainInfoKHR ที่ลิงก์กับโครงสร้าง VkBindImageMemoryInfo imageIndex ที่ระบุในโครงสร้าง VkBindImageMemorySwapchainInfoKHR ต้องเป็นดัชนีรูปภาพ Swapchain ที่ถูกต้อง ขณะเดียวกัน แพลตฟอร์มจะจัดเตรียมโครงสร้างส่วนขยาย VkNativeBufferANDROID ที่มีข้อมูลบัฟเฟอร์ Gralloc ที่เกี่ยวข้องให้กับเชน VkBindImageMemoryInfo เพื่อให้ไดรเวอร์ทราบว่าต้องเชื่อมโยง VkImage กับบัฟเฟอร์ Gralloc รายการใด

ถ่ายภาพ

vkAcquireImageANDROID ได้รับความเป็นเจ้าของรูปภาพ Swapchain และนําเข้ารั้วเนทีฟที่ส่งสัญญาณจากภายนอกไปยังทั้งออบเจ็กต์ VkSemaphore ที่มีอยู่และออบเจ็กต์ VkFence ที่มีอยู่ ดังนี้

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

vkAcquireImageANDROID() จะเรียกใช้ระหว่างvkAcquireNextImageKHRเพื่อนําเข้ารั้วแบบดั้งเดิมไปยังออบเจ็กต์ VkSemaphore และ VkFence ที่ได้จากแอป (อย่างไรก็ตาม คุณจะใช้ทั้งออบเจ็กต์ Semaphore และรั้วในคําเรียกนี้หรือไม่ก็ได้) ผู้ขับขี่อาจใช้โอกาสนี้ในการจดจำและจัดการการเปลี่ยนแปลงภายนอกกับสถานะบัฟเฟอร์ Gralloc ซึ่งผู้ขับขี่จำนวนมากไม่จำเป็นต้องดำเนินการใดๆ ที่นี่ การเรียกนี้จะทำให้ VkSemaphore และ VkFence อยู่ในสถานะรอดำเนินการเดียวกันกับที่ได้รับสัญญาณจาก vkQueueSubmit เพื่อให้คิวรอที่เซมาโฟร์และแอปรอที่รั้วได้

ทั้ง 2 ออบเจ็กต์จะได้รับการแจ้งเตือนเมื่อรั้วเนทีฟที่อยู่เบื้องล่างส่งสัญญาณ หากรั้วเนทีฟส่งสัญญาณแล้ว เซมาโฟร์จะอยู่ในสถานะ "ส่งสัญญาณแล้ว" เมื่อฟังก์ชันนี้แสดงผล โปรแกรมควบคุมจะเป็นเจ้าของตัวระบุไฟล์รั้วและปิดตัวระบุไฟล์รั้วเมื่อไม่จําเป็นต้องใช้อีกต่อไป โปรแกรมควบคุมต้องดำเนินการดังกล่าวแม้ว่าจะไม่มีการจัดหาออบเจ็กต์ Semaphore หรือ Fence ก็ตาม หรือแม้ว่าvkAcquireImageANDROIDจะดำเนินการไม่สำเร็จและแสดงข้อผิดพลาดก็ตาม หาก fenceFd เป็น -1 แสดงว่ารั้วเดิมได้รับการส่งสัญญาณแล้ว

เผยแพร่รูปภาพ

vkQueueSignalReleaseImageANDROIDเตรียมภาพ Swapchain สำหรับการใช้งานภายนอก สร้างรั้วแบบเนทีฟ และกำหนดเวลาให้ส่งสัญญาณรั้วแบบเนทีฟหลังจากที่เซมาโฟร์อินพุตส่งสัญญาณแล้ว โดยทำดังนี้

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

vkQueuePresentKHR() สาย vkQueueSignalReleaseImageANDROID() ในคิวที่ระบุ คนขับต้องสร้างรั้วแบบเนทีฟที่ไม่มีสัญญาณจนกว่าระบบจะแบ่งสัญญาณ waitSemaphoreCount ออกทั้งหมดในสัญญาณ pWaitSemaphores รวมทั้งต้องทำงานเพิ่มเติมที่จำเป็นเพื่อเตรียม image ให้พร้อมนำเสนอให้เสร็จสิ้น

หากสัญลักษณ์การรอ (หากมี) ส่งสัญญาณไว้แล้วและ queue ไม่มีการใช้งานอยู่แล้ว ไดรเวอร์อาจตั้งค่า *pNativeFenceFd เป็น -1 แทนตัวบ่งชี้ไฟล์แบบเนทีฟจริง ซึ่งแสดงว่าไม่มีอะไรให้รอ ผู้เรียกใช้เป็นเจ้าของและปิดตัวระบุไฟล์ที่แสดงใน *pNativeFenceFd

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

หากรูปภาพสร้างขึ้นด้วย VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID โปรแกรมควบคุมต้องอนุญาตให้เรียก vkQueueSignalReleaseImageANDROID() ซ้ำๆ ได้โดยไม่ต้องเรียก vkAcquireImageANDROID()

การสนับสนุนรูปภาพที่นำเสนอได้ที่แชร์ได้

อุปกรณ์บางเครื่องสามารถแชร์การเป็นเจ้าของรูปภาพเดียวระหว่างไปป์ไลน์การแสดงผลและการใช้ Vulkan เพื่อลดเวลาในการตอบสนอง ใน Android 9 ขึ้นไป โปรแกรมโหลดจะแสดงส่วนขยาย VK_KHR_shared_presentable_image แบบมีเงื่อนไขโดยอิงตามการตอบสนองของไดรเวอร์ต่อการเรียกใช้ vkGetPhysicalDeviceProperties2

หากไดรเวอร์ไม่รองรับ Vulkan 1.1 หรือส่วนขยาย VK_KHR_physical_device_properties2 โปรแกรมโหลดจะไม่แสดงการรองรับรูปภาพที่แสดงได้ซึ่งแชร์ มิเช่นนั้น โปรแกรมโหลดจะค้นหาความสามารถของไดรเวอร์โดยการเรียกใช้ vkGetPhysicalDeviceProperties2() และใส่โครงสร้างต่อไปนี้ในเชน VkPhysicalDeviceProperties2::pNext

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

หากไดรเวอร์สามารถแชร์ความเป็นเจ้าของรูปภาพกับระบบแสดงผลได้ ระบบจะตั้งค่าสมาชิก sharedImage เป็น VK_TRUE

การตรวจสอบความถูกต้อง

OEM สามารถทดสอบการใช้งาน Vulkan โดยใช้ CTS ซึ่งประกอบด้วยรายการต่อไปนี้

  • การทดสอบการปฏิบัติตามข้อกำหนดของ Khronos Vulkan ในข้อบังคับ CtsDeqpTestCases ซึ่งรวมถึงการทดสอบฟังก์ชันการทำงานของ API สำหรับ Vulkan 1.0, 1.1, 1.2 และ 1.3
  • โมดูล CtsGraphicsTestCases ซึ่งทดสอบว่าอุปกรณ์ได้รับการกำหนดค่าอย่างถูกต้องสำหรับความสามารถของ Vulkan ที่รองรับหรือไม่

แฟล็กฟีเจอร์ Vulkan

ต้องรองรับ Android 11 ขึ้นไปและรองรับ Vulkan API เพื่อแสดงแฟล็กฟีเจอร์ android.software.vulkan.deqp.level ค่าของ Flag ฟีเจอร์นี้คือวันที่ที่เข้ารหัสเป็นค่าจำนวนเต็ม โดยจะระบุวันที่ที่เชื่อมโยงกับการทดสอบ Vulkan dEQP ที่อุปกรณ์อ้างว่าผ่าน

วันที่ในรูปแบบ YYYY-MM-DD ได้รับการเข้ารหัสเป็นจำนวนเต็ม 32 บิต ดังนี้

  • บิต 0-15 จัดเก็บปี
  • บิต 16-23 จัดเก็บข้อมูลเดือน
  • ขายของ 24-31 ในแต่ละวัน

ค่าต่ำสุดที่อนุญาตสำหรับ Flag ฟีเจอร์คือ 0x07E30301 ซึ่งสอดคล้องกับวันที่ 01-03-2019 ซึ่งเป็นวันที่เชื่อมโยงกับการทดสอบ dEQP ของ Vulkan สำหรับ Android 10 หาก Flag ฟีเจอร์มีค่าอย่างน้อยเท่านี้ อุปกรณ์จะถือว่าผ่านการทดสอบ dEQP ของ Vulkan ใน Android 10 ทั้งหมด

ค่า 0x07E40301 สอดคล้องกับวันที่ 01-03-2020 ซึ่งเป็นวันที่เชื่อมโยงกับการทดสอบ dEQP ของ Vulkan สำหรับ Android 11 หาก Flag ฟีเจอร์มีค่าอย่างน้อยเท่านี้ แสดงว่าอุปกรณ์ผ่านการทดสอบ dEQP ของ Vulkan ใน Android 11 ทั้งหมด

ค่า 0x07E60301 สอดคล้องกับวันที่ 01-03-2022 ซึ่งเป็นวันที่เชื่อมโยงกับการทดสอบ dEQP ของ Vulkan สำหรับ Android 13 หาก Flag ฟีเจอร์มีค่าอย่างน้อยเท่านี้ อุปกรณ์จะถือว่าผ่านการทดสอบ Vulkan dEQP ทั้งหมดของ Android 13

อุปกรณ์ที่แสดง Flag ฟีเจอร์ที่เจาะจง (เช่น 0x07E30301, 0x07E40301, 0x07E60301) อ้างว่าผ่านการทดสอบ dEQP ของ Android Vulkan ทั้งหมดของฟีเจอร์ดังกล่าว (Android 10, Android 11, Android 13 ตามลำดับ) อุปกรณ์นี้อาจผ่านการทดสอบ Vulkan dEQP จาก Android เวอร์ชันที่ใหม่กว่า

Vulkan dEQP เป็นส่วนหนึ่งของ Android CTS ตั้งแต่ Android 11 เป็นต้นไป คอมโพเนนต์โปรแกรมรันทดสอบ dEQP ของ CTS จะรับรู้ถึง Flag ฟีเจอร์ android.software.vulkan.deqp.level และข้ามการทดสอบ Vulkan dEQP ที่อุปกรณ์ไม่ได้อ้างว่ารองรับตาม Flag ฟีเจอร์นี้ การทดสอบดังกล่าวจะได้รับการรายงานว่าผ่าน