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

รูปที่ 1 การลิงก์รหัสผู้ให้บริการกับไลบรารีภายใน
ความแตกต่างจาก RenderScript ใน Android 7.x และต่ำกว่ามีดังนี้
- อินสแตนซ์ของไลบรารีภายใน RenderScript 2 รายการในกระบวนการ ชุดหนึ่งใช้สำหรับ
เส้นทางการสำรองของ CPU และมาจาก
/system/lib
โดยตรง ส่วนอีกชุด ใช้สำหรับเส้นทาง GPU และมาจาก/system/lib/vndk-sp
- ไลบรารีภายในของ RS ใน
/system/lib
สร้างขึ้นเป็นส่วนหนึ่งของ แพลตฟอร์มและจะได้รับการอัปเดตเมื่อมีการอัปเกรดsystem.img
อย่างไรก็ตาม lib ใน/system/lib/vndk-sp
สร้างขึ้นสำหรับผู้ให้บริการและจะไม่ อัปเดตเมื่ออัปเกรดsystem.img
(แม้ว่าจะอัปเดตได้ เพื่อแก้ไขด้านความปลอดภัย แต่ ABI จะยังคงเหมือนเดิม) - โค้ดของผู้ให้บริการ (RS HAL, ไดรเวอร์ RS และ
bcc plugin
) จะ ลิงก์กับไลบรารีภายในของ RenderScript ซึ่งอยู่ที่/system/lib/vndk-sp
โดยจะลิงก์กับไลบรารีใน/system/lib
ไม่ได้เนื่องจากไลบรารีในไดเรกทอรีนั้นสร้างขึ้นสำหรับแพลตฟอร์ม จึงอาจไม่เข้ากันกับโค้ดของผู้ให้บริการ (เช่น อาจมีการนำสัญลักษณ์ออก) การดำเนินการดังกล่าวจะทำให้ OTA ที่มีเฉพาะเฟรมเวิร์กเป็นไปไม่ได้
การออกแบบ
ส่วนต่อไปนี้จะอธิบายรายละเอียดการออกแบบ RenderScript ใน Android 8.0 ขึ้นไป
ไลบรารี RenderScript พร้อมให้บริการแก่ผู้ให้บริการ
ส่วนนี้แสดงรายการไลบรารี RenderScript (หรือที่เรียกว่า Vendor NDK สำหรับ HAL ในกระบวนการเดียวกัน หรือ VNDK-SP) ที่พร้อมใช้งานสำหรับโค้ดของผู้ให้บริการและสามารถลิงก์ ได้ นอกจากนี้ ยังมีรายละเอียดไลบรารีเพิ่มเติมที่ไม่เกี่ยวข้องกับ RenderScript แต่มีให้ในโค้ดของผู้ให้บริการด้วย
แม้ว่ารายการไลบรารีต่อไปนี้อาจแตกต่างกันระหว่าง Android แต่ละรุ่น
แต่จะไม่มีการเปลี่ยนแปลงสำหรับ Android รุ่นใดรุ่นหนึ่ง หากต้องการดูรายการไลบรารีที่
พร้อมใช้งานล่าสุด โปรดดูที่ /system/etc/ld.config.txt
RenderScript Libs | Libs ที่ไม่ใช่ RenderScript |
---|---|
|
|
การกำหนดค่าเนมสเปซ Linker
การจำกัดการลิงก์ที่ป้องกันไม่ให้โค้ดของผู้ให้บริการใช้ไลบรารีที่ไม่ได้อยู่ใน VNDK-SP จะมีผลที่รันไทม์โดยใช้เนมสเปซของลิงเกอร์ (ดูรายละเอียดได้ที่งานนำเสนอการออกแบบ VNDK )
ในอุปกรณ์ที่ใช้ Android 8.0 ขึ้นไป HAL ทั้งหมดในกระบวนการเดียวกัน (SP-HAL)
ยกเว้น RenderScript จะโหลดภายในเนมสเปซของ Linker
sphal
RenderScript จะโหลดลงในเนมสเปซ rs
เฉพาะของ RenderScript ซึ่งเป็นตำแหน่งที่ช่วยให้การบังคับใช้ไลบรารี RenderScript มีความยืดหยุ่นมากขึ้นเล็กน้อย
เนื่องจากการติดตั้งใช้งาน RS ต้องโหลดบิตโค้ดที่คอมไพล์แล้ว เราจึงเพิ่ม /data/*/*.so
ลงในเส้นทางของเนมสเปซ rs
(SP-HAL อื่นๆ จะโหลดไลบรารีจากพาร์ติชันข้อมูลไม่ได้)
นอกจากนี้ เนมสเปซ rs
ยังอนุญาตให้ใช้ไลบรารีได้มากกว่าที่เนมสเปซอื่นๆ
อนุญาต libmediandk.so
และ libft2.so
จะแสดงในเนมสเปซ rs
เนื่องจาก
libRS_internal.so
มีทรัพยากร Dependency ภายในสำหรับไลบรารีเหล่านี้

รูปที่ 2 การกำหนดค่าเนมสเปซสำหรับ Linker
โหลดไดรเวอร์
เส้นทางการสำรองของ CPU
เมื่อสร้างบริบท RS ระบบจะเลือกเส้นทาง CPU หรือ GPU ทั้งนี้ขึ้นอยู่กับว่ามี RS_CONTEXT_LOW_LATENCY
บิต
หรือไม่ เมื่อเลือกเส้นทาง CPU ระบบจะlibRS_internal.so
(การใช้งานหลัก
ของเฟรมเวิร์ก RS) dlopen
โดยตรงจากเนมสเปซของ Linker เริ่มต้น
ซึ่งมีไลบรารี RS เวอร์ชันแพลตฟอร์ม
ระบบจะไม่ใช้การติดตั้งใช้งาน RS HAL จากผู้ให้บริการเลยเมื่อใช้เส้นทางการสำรองของ CPU
และจะสร้างออบเจ็กต์ RsContext
โดยมี mVendorDriverName
เป็นค่าว่าง
libRSDriver.so
จะdlopen
(โดยค่าเริ่มต้น) และโหลดไลบรารีไดรเวอร์จากเนมสเปซ default
เนื่องจากโหลดโปรแกรมเรียกใช้ (libRS_internal.so
) ในเนมสเปซ default
ด้วย

รูปที่ 3 เส้นทางการสำรองของ CPU
เส้นทาง GPU
สำหรับเส้นทาง GPU ระบบจะโหลด libRS_internal.so
ในลักษณะที่แตกต่างกัน
ก่อนอื่น libRS.so
ใช้
android.hardware.renderscript@1.0.so
(และ
libhidltransport.so
ที่อยู่เบื้องหลัง) เพื่อโหลด
android.hardware.renderscript@1.0-impl.so
(การติดตั้งใช้งาน RS HAL ของผู้ให้บริการ) ลงในเนมสเปซของ Linker อื่นที่ชื่อว่า
sphal
จากนั้น RS
HAL จะdlopen
libRS_internal.so
ในเนมสเปซของลิงเกอร์อีกอันที่ชื่อ rs
ผู้ให้บริการสามารถจัดหาไดรเวอร์ RS ของตนเองได้โดยการตั้งค่าสถานะเวลาบิลด์
OVERRIDE_RS_DRIVER
ซึ่งฝังอยู่ในการติดตั้งใช้งาน RS HAL
(hardware/interfaces/renderscript/1.0/default/Context.cpp
) จากนั้นจะdlopen
ชื่อไดรเวอร์นี้สำหรับบริบท RS สำหรับเส้นทาง GPU
การสร้างออบเจ็กต์ RsContext
จะมอบหมายให้การติดตั้งใช้งาน RS HAL
HAL จะเรียกกลับไปยังเฟรมเวิร์ก RS โดยใช้ฟังก์ชัน rsContextCreateVendor()
ที่มีชื่อไดรเวอร์เพื่อใช้เป็นอาร์กิวเมนต์ จากนั้นเฟรมเวิร์ก RS จะโหลดไดรเวอร์ที่ระบุเมื่อมีการเริ่มต้น RsContext
ในกรณีนี้ ระบบจะโหลดไลบรารีไดรเวอร์ลงในเนมสเปซ rs
เนื่องจากมีการสร้างออบเจ็กต์ RsContext
ภายในเนมสเปซ rs
และ /vendor/lib
อยู่ในเส้นทางการค้นหาของเนมสเปซ

รูปที่ 4 เส้นทางการสำรองของ GPU
เมื่อเปลี่ยนจากเนมสเปซ default
เป็นเนมสเปซ
sphal
libhidltransport.so
จะใช้ฟังก์ชัน
android_load_sphal_library()
เพื่อสั่งให้
โปรแกรมลิงก์แบบไดนามิกโหลดไลบรารี -impl.so
จากเนมสเปซ
sphal
อย่างชัดเจน
เมื่อเปลี่ยนจากเนมสเปซ sphal
เป็นเนมสเปซ
rs
การโหลดจะทำโดยอ้อมผ่านบรรทัดต่อไปนี้ใน
/system/etc/ld.config.txt
namespace.sphal.link.rs.shared_libs = libRS_internal.so
บรรทัดนี้ระบุว่าตัวลิงก์แบบไดนามิกควรโหลด
libRS_internal.so
จากเนมสเปซ rs
เมื่อไม่พบ/โหลด lib
จากเนมสเปซ sphal
(ซึ่งเป็นกรณีที่เกิดขึ้นเสมอเนื่องจากเนมสเปซ sphal
ไม่ได้ค้นหา
/system/lib/vndk-sp
ที่ libRS_internal.so
อยู่) การกำหนดค่านี้ทำให้การเรียกใช้ dlopen()
แบบง่ายๆ ไปยัง
libRS_internal.so
เพียงพอที่จะทำการเปลี่ยนเนมสเปซ
โหลดปลั๊กอินสำเนาลับ
bcc plugin
คือไลบรารีที่ผู้ให้บริการจัดหาให้ซึ่งโหลดลงในคอมไพเลอร์ bcc
เนื่องจาก bcc
เป็นกระบวนการของระบบในไดเรกทอรี /system/bin
จึงถือว่าไลบรารี bcc plugin
เป็น SP-HAL (กล่าวคือ HAL ของผู้ให้บริการที่โหลดลงในกระบวนการของระบบได้โดยตรงโดยไม่ต้องใช้ Binder) ในฐานะ SP-HAL
bcc-plugin
ไลบรารี:
- ลิงก์กับไลบรารีที่ใช้เฟรมเวิร์กเท่านั้นไม่ได้ เช่น
libLLVM.so
- ลิงก์ได้เฉพาะกับไลบรารี VNDK-SP ที่ผู้ให้บริการมีเท่านั้น
การบังคับใช้ข้อจำกัดนี้ทำได้โดยการโหลด bcc plugin
ลงในเนมสเปซ sphal
โดยใช้ฟังก์ชัน android_sphal_load_library()
ใน Android เวอร์ชันก่อนหน้า ชื่อปลั๊กอินจะระบุโดยใช้ตัวเลือก -load
และ
โหลด lib โดยใช้ dlopen()
อย่างง่ายโดย libLLVM.so
ใน Android 8.0 ขึ้นไป จะมีการระบุใน-plugin
option และbcc
จะโหลด lib โดยตรง ตัวเลือกนี้จะเปิดใช้เส้นทางที่ไม่เจาะจง Android ไปยัง
โปรเจ็กต์ LLVM แบบโอเพนซอร์ส

รูปที่ 5 กำลังโหลดปลั๊กอิน bcc, Android 7.x และต่ำกว่า

รูปที่ 6 กำลังโหลดปลั๊กอิน bcc, Android 8.0 ขึ้นไป
เส้นทางการค้นหาสำหรับ ld.mc
เมื่อเรียกใช้ ld.mc
ระบบจะป้อนไลบรารีรันไทม์ RS บางรายการเป็นอินพุต
ไปยัง Linker บิตโค้ด RS จากแอปจะลิงก์กับไลบรารีรันไทม์
และเมื่อโหลดบิตโค้ดที่แปลงแล้วลงในกระบวนการของแอป ไลบรารีรันไทม์
จะลิงก์แบบไดนามิกจากบิตโค้ดที่แปลงแล้วอีกครั้ง
ไลบรารีรันไทม์ประกอบด้วย
libcompiler_rt.so
libm.so
libc.so
- นักขับ RS (
libRSDriver.so
หรือOVERRIDE_RS_DRIVER
)
เมื่อโหลดบิตโค้ดที่คอมไพล์แล้วลงในกระบวนการของแอป ให้ระบุไลบรารีที่เหมือนกับที่ ld.mc
ใช้ทุกประการ
ไม่เช่นนั้น บิตโค้ดที่คอมไพล์
อาจไม่พบสัญลักษณ์ที่พร้อมใช้งานเมื่อมีการลิงก์
โดยเฟรมเวิร์ก RS จะใช้เส้นทางการค้นหาที่แตกต่างกันสำหรับไลบรารีรันไทม์เมื่อ
เรียกใช้ ld.mc
ทั้งนี้ขึ้นอยู่กับว่าเฟรมเวิร์ก RS เองโหลดจาก /system/lib
หรือจาก /system/lib/vndk-sp
ซึ่งสามารถกำหนดได้โดยการอ่านที่อยู่ของสัญลักษณ์ใดก็ได้ของไลบรารีเฟรมเวิร์ก RS
และใช้ dladdr()
เพื่อรับเส้นทางไฟล์ที่แมปกับ
ที่อยู่
นโยบาย SELinux
การเปลี่ยนแปลงนโยบาย SELinux ใน Android 8.0 ขึ้นไปทำให้คุณต้อง
ทำตามกฎที่เฉพาะเจาะจง (บังคับใช้ผ่าน neverallows
) เมื่อ
ติดป้ายกำกับไฟล์เพิ่มเติมในพาร์ติชัน vendor
vendor_file
ต้องเป็นป้ายกำกับเริ่มต้นสำหรับไฟล์ทั้งหมดในพาร์ติชันvendor
นโยบายแพลตฟอร์มกำหนดให้ต้องดำเนินการนี้เพื่อเข้าถึง การติดตั้งใช้งาน HAL แบบส่งผ่านexec_types
ใหม่ทั้งหมดที่เพิ่มในพาร์ติชันvendor
ผ่าน SEPolicy ของผู้ให้บริการต้องมีแอตทริบิวต์vendor_file_type
ซึ่งจะบังคับใช้ผ่านneverallows
- หากต้องการหลีกเลี่ยงไม่ให้เกิดข้อขัดแย้งกับการอัปเดตแพลตฟอร์ม/เฟรมเวิร์กในอนาคต ให้หลีกเลี่ยงการติดป้ายกำกับไฟล์อื่นๆ นอกเหนือจาก
exec_types
ในพาร์ติชันvendor
- การขึ้นต่อกันของไลบรารีทั้งหมดสำหรับ HAL ของกระบวนการเดียวกันที่ AOSP ระบุต้องมีป้ายกำกับเป็น
same_process_hal_file
ดูรายละเอียดเกี่ยวกับนโยบาย SELinux ได้ที่ Security-Enhanced Linux ใน Android
ความเข้ากันได้ของ ABI สำหรับบิตโค้ด
หากไม่มีการเพิ่ม API ใหม่ ซึ่งหมายความว่าไม่มีการเพิ่มเวอร์ชัน HAL เฟรมเวิร์ก RS จะใช้ไดรเวอร์ GPU (HAL 1.0) ที่มีอยู่ต่อไป
สำหรับการเปลี่ยนแปลง HAL เล็กน้อย (HAL 1.1) ที่ไม่ส่งผลต่อบิตโค้ด เฟรมเวิร์กควร ใช้ CPU เป็นทางเลือกสำรองสำหรับ API ที่เพิ่มใหม่เหล่านี้ และใช้ไดรเวอร์ GPU (HAL 1.0) ต่อไป ในที่อื่นๆ
สำหรับการเปลี่ยนแปลง HAL ที่สำคัญ (HAL 2.0) ซึ่งส่งผลต่อการคอมไพล์/ลิงก์บิตโค้ด เฟรมเวิร์ก RS ควรเลือกที่จะไม่โหลดไดรเวอร์ GPU ที่ผู้ให้บริการจัดหาให้ และใช้เส้นทาง CPU หรือ Vulkan แทน เพื่อการเร่งความเร็ว
การใช้บิตโค้ด RenderScript จะเกิดขึ้นใน 3 ขั้นตอนดังนี้
ขั้นตอน | รายละเอียด |
---|---|
รวบรวม |
|
ลิงก์ |
|
โหลด |
|
นอกจาก HAL แล้ว API รันไทม์และสัญลักษณ์ที่ส่งออกยังเป็นอินเทอร์เฟซด้วย ทั้ง 2 อินเทอร์เฟซไม่มีการเปลี่ยนแปลงตั้งแต่ Android 7.0 (API 24) และเรา ยังไม่มีแผนที่จะเปลี่ยนแปลงใน Android 8.0 ขึ้นไปในตอนนี้ อย่างไรก็ตาม หากอินเทอร์เฟซมีการเปลี่ยนแปลง เวอร์ชัน HAL ก็จะเพิ่มขึ้นด้วย
การติดตั้งใช้งานของผู้ให้บริการ
Android 8.0 ขึ้นไปต้องมีการเปลี่ยนแปลงไดรเวอร์ GPU บางอย่างเพื่อให้ไดรเวอร์ GPU ทำงานได้อย่างถูกต้อง
โมดูลไดรเวอร์
- โมดูลไดรเวอร์ต้องไม่ขึ้นอยู่กับไลบรารีของระบบที่ไม่ได้อยู่ในรายการ
- ไดรเวอร์ต้องระบุ
android.hardware.renderscript@1.0-impl_{NAME}
ของตัวเอง หรือประกาศการใช้งานเริ่มต้นandroid.hardware.renderscript@1.0-impl
เป็น การขึ้นต่อกัน - การใช้งาน CPU
libRSDriver.so
เป็นตัวอย่างที่ดีของวิธี นำการอ้างอิงที่ไม่ใช่ VNDK-SP ออก
คอมไพเลอร์บิตโค้ด
คุณคอมไพล์บิตโค้ด RenderScript สำหรับไดรเวอร์ของผู้ให้บริการได้ 2 วิธี ดังนี้
- เรียกใช้คอมไพเลอร์ RenderScript ของผู้ให้บริการใน
/vendor/bin/
(วิธีที่แนะนำสำหรับการคอมไพล์ GPU) ไบนารีของคอมไพเลอร์ของผู้ให้บริการต้องไม่ขึ้นอยู่กับไลบรารีของระบบที่ไม่ได้อยู่ในรายการไลบรารี RenderScript ที่พร้อมให้บริการแก่ผู้ให้บริการ เช่นเดียวกับโมดูลไดรเวอร์อื่นๆ - เรียกใช้ bcc ของระบบ:
/system/bin/bcc
โดยใช้bcc plugin
ที่ผู้ให้บริการระบุไว้ ปลั๊กอินนี้ต้องไม่ขึ้นอยู่กับไลบรารีของระบบที่ไม่ได้อยู่ในรายการไลบรารี RenderScript ที่พร้อมใช้งานสำหรับผู้ให้บริการ
หากผู้ให้บริการbcc plugin
จำเป็นต้องแทรกแซงการคอมไพล์ CPU
และไม่สามารถนำการขึ้นต่อกันของ libLLVM.so
ออกได้อย่างง่ายดาย
ผู้ให้บริการควรคัดลอก bcc
(และการขึ้นต่อกันที่ไม่ใช่ LL-NDK ทั้งหมด รวมถึง libLLVM.so
, libbcc.so
) ไปยังพาร์ติชัน /vendor
นอกจากนี้ ผู้ให้บริการยังต้องทำการเปลี่ยนแปลงต่อไปนี้ด้วย

รูปที่ 7 การเปลี่ยนแปลงไดรเวอร์ของผู้ให้บริการ
- คัดลอก
libclcore.bc
ไปยังพาร์ติชัน/vendor
ซึ่งจะช่วยให้libclcore.bc
,libLLVM.so
และlibbcc.so
ซิงค์กัน - เปลี่ยนเส้นทางไปยังไฟล์ปฏิบัติการ
bcc
โดยการตั้งค่าRsdCpuScriptImpl::BCC_EXE_PATH
จากการติดตั้งใช้งาน RS HAL
นโยบาย SELinux
นโยบาย SELinux มีผลต่อทั้งไดรเวอร์และไฟล์ปฏิบัติการของคอมไพเลอร์ โมดูลไดรเวอร์ทั้งหมดต้องมีป้ายกำกับ same_process_hal_file
ใน file_contexts
ของอุปกรณ์ เช่น
/vendor/lib(64)?/libRSDriver_EXAMPLE\.so u:object_r:same_process_hal_file:s0
แอปต้องเรียกใช้ไฟล์ปฏิบัติการของคอมไพเลอร์ได้ เช่นเดียวกับ
สำเนา bcc ของผู้ให้บริการ (/vendor/bin/bcc
) ตัวอย่างเช่น
device/vendor_foo/device_bar/sepolicy/file_contexts: /vendor/bin/bcc u:object_r:same_process_hal_file:s0
อุปกรณ์เดิม
อุปกรณ์รุ่นเดิมคืออุปกรณ์ที่มีคุณสมบัติตรงตามเงื่อนไขต่อไปนี้
- PRODUCT_SHIPPING_API_LEVEL ต่ำกว่า 26
- ไม่ได้กำหนด PRODUCT_FULL_TREBLE_OVERRIDE
สำหรับอุปกรณ์รุ่นเดิม ระบบจะไม่บังคับใช้ข้อจำกัดเมื่ออัปเกรดเป็น
Android 8.0 ขึ้นไป ซึ่งหมายความว่าไดรเวอร์จะยังคงลิงก์กับไลบรารีใน /system/lib[64]
ได้ อย่างไรก็ตาม เนื่องจากการเปลี่ยนแปลงสถาปัตยกรรม
ที่เกี่ยวข้องกับ OVERRIDE_RS_DRIVER
จึงต้องติดตั้ง android.hardware.renderscript@1.0-impl
ในพาร์ติชัน /vendor
หากไม่ทำเช่นนั้น รันไทม์ RenderScript จะต้องกลับไปใช้เส้นทาง CPU
ดูข้อมูลเกี่ยวกับแรงจูงใจในการเลิกใช้งาน RenderScript ได้ที่บล็อกของนักพัฒนาแอป Android ในหัวข้อการประมวลผล GPU ของ Android ในอนาคต ข้อมูลทรัพยากรสำหรับการเลิกใช้งานนี้ประกอบด้วยข้อมูลต่อไปนี้
- ย้ายข้อมูลจาก Renderscript
- ตัวอย่างการย้ายข้อมูล RenderScript
- ชุดเครื่องมือแทนที่ฟังก์ชันในตัว README
- Intrinsics ReplacementToolkit.kt