เราจะเลิกใช้งาน RenderScript API ใน Android 12 เป็นต้นไป อุปกรณ์และคอมโพเนนต์ ซึ่งผู้ผลิตส่วนใหญ่ก็หยุดให้การสนับสนุน การเร่งฮาร์ดแวร์แล้ว และคาดว่าจะนำการรองรับ RenderScript ออกทั้งหมดในเวอร์ชันในอนาคต
ประสิทธิภาพของ C/C++ อาจเพียงพอสำหรับการใช้งานในหลายกรณี และหากคุณ ซึ่งใช้ RenderScript เพื่อแทรกองค์ประกอบภายใน คุณสามารถแทนที่การใช้งานเหล่านั้นด้วย RenderScript Intrinsics Replacement Toolkit ซึ่งทำได้ง่ายกว่า เพื่อใช้งานและยังอาจได้รับการปรับปรุงประสิทธิภาพเพิ่มขึ้นถึง 2 เท่า
หากคุณต้องการใช้ประโยชน์จากการเร่ง GPU อย่างเต็มที่ เราขอแนะนำ การย้ายข้อมูลสคริปต์ไปยัง Vulkan, ตัวเลือกอื่นๆ แบบเร่ง รวมถึงการย้ายข้อมูลสคริปต์ไปยัง OpenGL โดยใช้แบบ Canvas การทำงานกับรูปภาพ หรือใช้ประโยชน์จากการลงสีกราฟิกของ Android ภาษา (AGSL)
หลังจากเลิกใช้งาน RenderScript ในแพลตฟอร์ม Android แล้ว การรองรับสำหรับ กำลังนำ RenderScript ออกในปลั๊กอิน Android Gradle เริ่มต้นด้วย ปลั๊กอิน Android Gradle 7.2, เลิกใช้งาน RenderScript API แล้ว โฆษณาเหล่านี้ ทำงานต่อไปได้ แต่จะเรียกใช้คำเตือน จะไม่มี AGP เวอร์ชันในอนาคตอีกต่อไป รวมถึงการรองรับ Renderscript คู่มือนี้จะอธิบายวิธีย้ายข้อมูลจาก RenderScript
ย้ายข้อมูลจาก Intinsics
แม้ว่าฟังก์ชันภายในของ RenderScript จะยังคงทำงานต่อไปหลังจาก การเลิกใช้งาน RenderScript อาจดำเนินการบน CPU เท่านั้นแทนที่จะเป็น GPU
การดำเนินการบางส่วนจะมีตัวเลือกที่มีประสิทธิภาพมากขึ้นรวมอยู่ใน แพลตฟอร์มหรือในคลัง Jetpack
การทำงานของอิมเมจแบบเร่งในตัว
แพลตฟอร์ม Android รองรับการประมวลผลรูปภาพแบบเร่งที่สามารถ สามารถใช้กับรูปภาพ ซึ่งไม่เกี่ยวข้องกับภายใน RenderScript ตัวอย่างเช่น
- รวม
- เบลอ
- เมตริกซ์สี
- ปรับขนาด
การเบลอรูปภาพใน Android 12 ขึ้นไปให้เป็น View
RenderEffect
ที่รองรับการเบลอเพิ่มเข้ามาใน Android 12
API ระดับ 31 ที่จะช่วยให้คุณเบลอ RenderNode
ได้ RenderNode
เป็นโครงสร้างของรายการ Display ที่ Android ใช้เพื่อช่วยเพิ่ม
กราฟิกแพลตฟอร์ม
Android มีทางลัดเพื่อใช้เอฟเฟกต์กับ RenderNode
ที่เชื่อมโยง
ด้วย View
หากต้องการเบลอ View
โปรดโทร
View.setRenderEffect()
:
val blurRenderEffect = RenderEffect.createBlurEffect(radius, radius,
Shader.TileMode.MIRROR
)
view.setRenderEffect(blurRenderEffect)
รูปภาพที่เบลอใน Android 12 ขึ้นไปที่แสดงผลเป็นบิตแมป
หากต้องการให้รูปภาพเบลอที่แสดงผลเป็นBitmap
เฟรมเวิร์ก
รองรับการแสดงผลแบบเร่งด้วย HardwareRenderer
สนับสนุนโดย HardwareBuffer
โค้ดต่อไปนี้สร้าง
HardwareRenderer
, RenderNode
และ RenderEffect
สำหรับการเบลอ
val imageReader = ImageReader.newInstance(
bitmap.width, bitmap.height,
PixelFormat.RGBA_8888, numberOfOutputImages,
HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE or HardwareBuffer.USAGE_GPU_COLOR_OUTPUT
)
val renderNode = RenderNode("BlurEffect")
val hardwareRenderer = HardwareRenderer()
hardwareRenderer.setSurface(imageReader.surface)
hardwareRenderer.setContentRoot(renderNode)
renderNode.setPosition(0, 0, imageReader.width, imageReader.height)
val blurRenderEffect = RenderEffect.createBlurEffect(
radius, radius,
Shader.TileMode.MIRROR
)
renderNode.setRenderEffect(blurRenderEffect)
การใช้เอฟเฟ็กต์เกี่ยวข้องกับการใช้องค์ประกอบภายใน
RecordingCanvas
สำหรับ RenderNode
รหัสต่อไปนี้
บันทึกภาพวาด สร้างคำขอแสดงผล แล้วรอให้
ขอให้สิ้นสุด:
val renderCanvas = it.renderNode.beginRecording()
renderCanvas.drawBitmap(it.bitmap, 0f, 0f, null)
renderNode.endRecording()
hardwareRenderer.createRenderRequest()
.setWaitForPresent(true)
.syncAndDraw()
รูปภาพที่แสดงอยู่ใน HardwareBuffer
ที่เชื่อมโยงกับ
ImageReader
โค้ดต่อไปนี้ได้รับ Image
และ
แสดงผล Bitmap
ที่รวม HardwareBuffer
val image = imageReader.acquireNextImage() ?: throw RuntimeException("No Image")
val hardwareBuffer = image.hardwareBuffer ?: throw RuntimeException("No HardwareBuffer")
val bitmap = Bitmap.wrapHardwareBuffer(hardwareBuffer, null)
?: throw RuntimeException("Create Bitmap Failed")
โค้ดต่อไปนี้จะล้างออกหลังจากแสดงภาพ โปรดทราบว่า
ImageReader
, RenderNode
, RenderEffect
และ HardwareRenderer
เพื่อประมวลผลรูปภาพหลายรูป
hardwareBuffer.close()
image.close()
imageReader.close()
renderNode.discardDisplayList()
hardwareRenderer.destroy()
AGSL สำหรับการประมวลผลรูปภาพ
Android 13 ขึ้นไปใช้ Android Graphics Shading Language (AGSL) เพื่อ
กำหนดลักษณะการทำงานของ Programmable
ออบเจ็กต์ RuntimeShader
AGSL
แชร์ไวยากรณ์ส่วนใหญ่กับตัวปรับแสงเงา Fragment ของ GLSL แต่ใช้งานได้ภายใน
ระบบแสดงผลกราฟิก Android สำหรับการปรับแต่งภาพวาดภายใน Canvas
และกรองเนื้อหา View
สามารถใช้เพื่อเพิ่มการประมวลผลรูปภาพที่กำหนดเอง
ระหว่างการวาด หรือใช้ RenderNode
โดยตรงเพื่อแสดงผล
ลงในแคนวาสขนาด Bitmap
ตัวอย่างต่อไปนี้สาธิตวิธีใช้
ตัวปรับแสงเงาที่กำหนดเองเพื่อใช้แทนเอฟเฟ็กต์เบลอภาพ
เริ่มต้นด้วยการสร้าง RuntimeShader
เริ่มต้นอินสแตนซ์ด้วยตัวปรับแสงเงา AGSL
โค้ด ตัวปรับเฉดสีนี้ใช้เมทริกซ์สีสำหรับการหมุนโทนสี
val hueShader = RuntimeShader("""
uniform float2 iResolution; // Viewport resolution (pixels)
uniform float2 iImageResolution; // iImage1 resolution (pixels)
uniform float iRadian; // radian to rotate things around
uniform shader iImage1; // An input image
half4 main(float2 fragCoord) {
float cosR = cos(iRadian);
float sinR = sin(iRadian);
mat4 hueRotation =
mat4 (
0.299 + 0.701 * cosR + 0.168 * sinR, //0
0.587 - 0.587 * cosR + 0.330 * sinR, //1
0.114 - 0.114 * cosR - 0.497 * sinR, //2
0.0, //3
0.299 - 0.299 * cosR - 0.328 * sinR, //4
0.587 + 0.413 * cosR + 0.035 * sinR, //5
0.114 - 0.114 * cosR + 0.292 * sinR, //6
0.0, //7
0.299 - 0.300 * cosR + 1.25 * sinR, //8
0.587 - 0.588 * cosR - 1.05 * sinR, //9
0.114 + 0.886 * cosR - 0.203 * sinR, //10
0.0, //11
0.0, 0.0, 0.0, 1.0 ); //12,13,14,15
float2 scale = iImageResolution.xy / iResolution.xy;
return iImage1.eval(fragCoord * scale)*hueRotation;
}
""")
สามารถใช้ตัวปรับแสงเงากับ RenderNode
ได้เช่นเดียวกับ RenderEffect
อื่นๆ
ตัวอย่างต่อไปนี้แสดงวิธีจัดเครื่องแบบใน HueShader
hueShader.setFloatUniform("iImageResolution", bitmap.width.toFloat(),
bitmap.height.toFloat())
hueShader.setFloatUniform("iResolution", bitmap.width.toFloat(),
bitmap.height.toFloat())
hueShader.setFloatUniform("iRadian", radian)
hueShader.setInputShader( "iImage1", BitmapShader(bitmap, Shader.TileMode.MIRROR,
Shader.TileMode.MIRROR))
val colorFilterEffect = RenderEffect.createShaderEffect(it.hueShader)
renderNode.setRenderEffect(colorFilterEffect)
หากต้องการได้ Bitmap
จะใช้เทคนิคเดียวกับการเบลอรูปภาพก่อนหน้า
ตัวอย่าง
- ภายใน
RecordingCanvas
สำหรับRenderNode
จะใช้ตัวปรับแสงเงา - ได้รับ
Image
แล้ว และแสดงผลBitmap
ที่รวมHardwareBuffer
แปลงจาก YUV แบบระนาบเป็น RGB โดยใช้ CameraX
กำลังแปลงจาก YUV ระนาบ เป็น RGB เพื่อใช้ในการประมวลผลรูปภาพได้รับการสนับสนุนโดยเป็นส่วนหนึ่งของ กรณีการใช้งาน ImageAnalysis ภายใน Jetpack CameraX
มีแหล่งข้อมูลเกี่ยวกับการใช้ ImageAnalysis
เป็นส่วนหนึ่งของ
เริ่มต้นใช้งาน CameraX Codelab และใน
กล้อง Android
ตัวอย่าง
ชุดเครื่องมือแทนที่ภายใน Renderscript
หากแอปพลิเคชันของคุณใช้ภายใน คุณสามารถใช้การเปลี่ยนแบบสแตนด์อโลนได้ คลัง; การทดสอบของเราชี้ให้เห็นว่าสามารถเร็วกว่าการใช้ CPU ของ RenderScript ที่มีอยู่ การใช้งานของคุณ
ชุดเครื่องมือประกอบด้วยฟังก์ชันการทำงานต่อไปนี้
- รวม
- เบลอ
- เมตริกซ์สี
- คอนโวล์ฟ
- ฮิสโตแกรมและฮิสโตแกรมดอท
- ตารางตรวจสอบ (LUT) และ LUT แบบ 3 มิติ
- ปรับขนาด
- YUV เป็น RGB
ดูรายละเอียดและข้อจำกัดทั้งหมดได้ที่ README.md
และ Toolkit.kt
ของชุดเครื่องมือ
ทําตามขั้นตอนต่อไปนี้เพื่อดาวน์โหลด เพิ่ม และใช้ไลบรารี
ดาวน์โหลดโปรเจ็กต์ จาก GitHub
ค้นหาและสร้าง
renderscript-toolkit module
เพิ่มไลบรารีลงในโปรเจ็กต์ Android Studio โดยแก้ไข
build.gradle
ไฟล์เรียกใช้วิธีการที่เหมาะสมของชุดเครื่องมือ
ตัวอย่าง: ย้ายข้อมูลจากฟังก์ชัน ScriptIntrinsicBlur
วิธีแทนที่ฟังก์ชัน ScriptIntrinsicBlur
หากต้องการเบลอบิตแมป ให้โทรหา
Toolkit.blur
var blurredBitmap = Toolkit.blur(myBitmap, radius)
หากต้องการเบลอภาพที่แสดงด้วยอาร์เรย์ของไบต์ ให้ระบุแอตทริบิวต์ ความกว้าง ความสูง และจำนวนไบต์ต่อพิกเซล
val outArray = Toolkit.blur(inputArray, bytesPerPixel, width, height, radius)
ย้ายข้อมูลจากสคริปต์
หากกรณีการใช้งานของคุณแก้ปัญหาด้วยไม่ได้
- ชุดเครื่องมือแทนที่ RenderScript Intrinsics
- API ใหม่ภายในแพลตฟอร์ม Android เช่น
RenderEffect
และAGSL
- API ไลบรารี Android Jetpack เช่น
CameraX
และกรณีการใช้งานของคุณจะได้รับประโยชน์จากการเร่ง GPU, Android รองรับ GPU ประมวลผลบน Vulkan และ OpenGL ES (GLES) API แบบข้ามแพลตฟอร์ม คุณอาจเห็นสิ่งนี้ ไม่จำเป็น เนื่องจากในอุปกรณ์ส่วนใหญ่ สคริปต์ของคุณทำงานอยู่บน CPU อยู่แล้ว แทน GPU: C/C++ อาจเร็วกว่า RenderScript, GLES หรือ Vulkan ประมวลผลสำหรับกรณีการใช้งานบางกรณี (หรืออย่างน้อยเร็วพอสำหรับกรณีการใช้งานของคุณ)
เพื่อให้เข้าใจวิธีย้ายข้อมูลได้ดีขึ้น โปรดอ่าน ตัวอย่างแอป ตัวอย่างที่สาธิตวิธีเบลอบิตแมปและการแปลงเมตริกซ์สี ใน RenderScript และมีโค้ดที่เทียบเท่าใน Vulkan และ OpenGL
หากแอปพลิเคชันของคุณต้องรองรับการเปิดตัวรุ่นต่างๆ ให้ใช้ RenderScript สำหรับ
อุปกรณ์ที่ใช้ Android 6 (API ระดับ 23) และต่ำกว่า รวมถึงเปิดใช้ Vulkan หรือ GLES
อุปกรณ์ที่รองรับ Android 7 (API ระดับ 24) ขึ้นไป หาก
minSdkVersion
มีอายุ 24 ปีขึ้นไป คุณอาจไม่จำเป็นต้องใช้ RenderScript Vulkan หรือ
คุณสามารถใช้ GLES 3.1 ได้ทุกที่ที่คุณต้องการการรองรับการประมวลผล GPU
Android มีการเชื่อมโยง SDK สำหรับ GLES API คุณจึงไม่จำเป็นต้องใช้ NDK เมื่อทำงานใน OpenGL ES
Vulkan ไม่มีการเชื่อมโยง SDK จึงไม่มีการแมปโดยตรงจาก RenderScript ไปยัง Vulkan คุณเขียนโค้ด Vulkan โดยใช้ NDK และสร้าง JNI เข้าถึงโค้ดนี้จาก Kotlin หรือ Java
หน้าต่อไปนี้ครอบคลุมแง่มุมต่างๆ ของการย้ายข้อมูลจาก RenderScript ตัวอย่าง นำข้อควรพิจารณาเหล่านี้ไปใช้เกือบทั้งหมด เพื่อให้เข้าใจได้ดีขึ้น เปรียบเทียบโค้ดที่เทียบเท่าของ RenderScript และ Vulkan