RenderScript เป็นเฟรมเวิร์กสำหรับเรียกใช้งานที่มีการประมวลผลอย่างหนัก ด้วยประสิทธิภาพสูงใน Android โดยออกแบบมาเพื่อใช้กับการคำนวณแบบขนานข้อมูล แม้ว่าภาระงานแบบอนุกรมก็อาจได้รับประโยชน์เช่นกัน รันไทม์ RenderScript จะทำงานแบบขนานในตัวประมวลผลที่มีอยู่ในอุปกรณ์ เช่น CPU และ GPU แบบมัลติคอร์ ซึ่งช่วยให้นักพัฒนาแอปมุ่งเน้นที่การแสดงอัลกอริทึมแทนการกำหนดเวลาการทำงานได้ RenderScript มีประโยชน์อย่างยิ่งสำหรับแอปที่ประมวลผลรูปภาพ การถ่ายภาพเชิงคำนวณ หรือคอมพิวเตอร์วิทัศน์
อุปกรณ์ที่ใช้ Android 8.0 ขึ้นไปจะใช้เฟรมเวิร์ก RenderScript และ Vendor HAL ต่อไปนี้
รูปที่ 1 การลิงก์รหัสผู้ให้บริการกับไลบรารีภายใน
ความแตกต่างจาก RenderScript ใน Android 7.x และต่ำกว่ามีดังนี้
- อินสแตนซ์ 2 รายการของไลบรารีภายใน RenderScript ในกระบวนการ ชุดหนึ่งใช้สำหรับ
เส้นทางการสำรองของ 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 | ไลบรารีที่ไม่ใช่ RenderScript |
|---|---|
|
|
การกำหนดค่าเนมสเปซของ Linker
การจำกัดการลิงก์ที่ป้องกันไม่ให้โค้ดของผู้ให้บริการใช้ไลบรารีที่ไม่ได้อยู่ใน VNDK-SP จะมีผลที่รันไทม์โดยใช้เนมสเปซของ Linker (ดูรายละเอียดได้ที่งานนำเสนอการออกแบบ 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 มีการอ้างอิงภายในไปยังไลบรารีเหล่านี้
รูปที่ 2 การกำหนดค่าเนมสเปซสำหรับ Linker
โหลดไดรเวอร์
เส้นทางการสำรองของ CPU
เมื่อสร้างบริบท RS ระบบจะเลือกเส้นทาง CPU หรือ GPU ทั้งนี้ขึ้นอยู่กับว่ามี RS_CONTEXT_LOW_LATENCY บิต
หรือไม่ เมื่อเลือกเส้นทาง CPU ระบบจะlibRS_internal.so (การใช้งานหลัก
ของเฟรมเวิร์ก RS) โดยตรงจากเนมสเปซของ Linker เริ่มต้น
ซึ่งมีไลบรารี RS เวอร์ชันแพลตฟอร์มdlopen
ระบบจะไม่ใช้การติดตั้งใช้งาน 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 จะdlopenlibRS_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 และ bcc จะโหลด lib โดยตรง ตัวเลือกนี้จะเปิดใช้เส้นทางที่ไม่เจาะจง Android ไปยัง
โปรเจ็กต์ LLVM แบบโอเพนซอร์ส
รูปที่ 5 กำลังโหลดปลั๊กอิน bcc, Android 7.x และต่ำกว่า
รูปที่ 6 การโหลดปลั๊กอิน bcc, Android 8.0 ขึ้นไป
เส้นทางการค้นหาสำหรับ ld.mc
เมื่อเรียกใช้ ld.mc ระบบจะป้อนไลบรารีรันไทม์ RS บางรายการเป็นอินพุต
ไปยัง Linker บิตโค้ด RS จากแอปจะลิงก์กับไลบรารีรันไทม์
และเมื่อโหลดบิตโค้ดที่แปลงแล้วลงในกระบวนการของแอป ไลบรารีรันไทม์
จะลิงก์แบบไดนามิกจากบิตโค้ดที่แปลงแล้วอีกครั้ง
ไลบรารีรันไทม์ประกอบด้วย
libcompiler_rt.solibm.solibc.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เป็น ทรัพยากร Dependency - การใช้งาน 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: Android GPU Compute Going Forward ข้อมูลทรัพยากรสำหรับการเลิกใช้งานนี้ประกอบด้วยข้อมูลต่อไปนี้
- ย้ายข้อมูลจาก Renderscript
- ตัวอย่างการย้ายข้อมูล RenderScript
- ชุดเครื่องมือแทนที่ Intrinsics README
- Intrinsics ReplacementToolkit.kt