Jam*_*hao 7 android opengl-es renderscript
背景:
我想根据Android相机应用程序的代码添加实时过滤器.但Android相机应用程序的架构基于OpenGL ES 1.x. 我需要使用着色器来自定义我们的过滤器实现.但是,将相机应用程序更新为OpenGL ES 2.0非常困难.然后我必须找到一些其他方法来实现实时过滤器而不是OpenGL.经过一些研究,我决定使用渲染脚本.
问题:
我已经通过渲染脚本编写了一个简单过滤器的演示.它表明fps远低于OpenGL实现它.大约5 fps vs 15 fps.
问题:
Android官方异地说:RenderScript运行时将并行处理设备上可用的所有处理器(如多核CPU,GPU或DSP)的工作,使您可以专注于表达算法而不是调度工作或负载平衡.那为什么渲染脚本实现较慢?
如果渲染脚本不能满足我的要求,有没有更好的方法?
代码详情:
嗨,我和提问者在同一个团队中.我们想要编写一个基于渲染脚本的实时滤镜相机.在我们的测试演示项目中,我们使用了一个简单的过滤器:添加了覆盖过滤器ScriptC脚本的YuvToRGB IntrinsicScript.在OpenGL版本中,我们将相机数据设置为纹理,并使用着色器执行image-filter-procss.像这样:
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureYHandle);
    GLES20.glUniform1i(shader.uniforms.get("uTextureY"), 0);
    GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mTextureWidth,
            mTextureHeight, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE,
            mPixelsYBuffer.position(0));
在RenderScript版本中,我们将相机数据设置为Allocation,并使用script-kernals执行image-filter-procss.像这样:
    // The belowing code is from onPreviewFrame(byte[] data, Camera camera) which gives the camera frame data 
    byte[] imageData = datas[0];
    long timeBegin = System.currentTimeMillis();
    mYUVInAllocation.copyFrom(imageData);
    mYuv.setInput(mYUVInAllocation);
    mYuv.forEach(mRGBAAllocationA);
    // To make sure the process of YUVtoRGBA has finished!
    mRGBAAllocationA.copyTo(mOutBitmap);    
    Log.e(TAG, "RS time: YUV to RGBA : " + String.valueOf((System.currentTimeMillis() - timeBegin)));   
    mLayerScript.forEach_overlay(mRGBAAllocationA, mRGBAAllocationB);
    mRGBAAllocationB.copyTo(mOutBitmap);    
    Log.e(TAG, "RS time: overlay : " + String.valueOf((System.currentTimeMillis() - timeBegin)));
    mCameraSurPreview.refresh(mOutBitmap, mCameraDisplayOrientation, timeBegin);
这两个问题是:(1)RenderScript进程似乎比OpenGL进程慢.(2)根据我们的时间日志,使用内在脚本的YUV到RGBA的过程非常快,大约需要6ms; 但是使用scriptC的叠加过程非常慢,大约需要180ms.这是怎么发生的?
这是我们使用的ScriptC的rs-kernal代码(mLayerScript):
#pragma version(1)
#pragma rs java_package_name(**.renderscript)
#pragma stateFragment(parent)
#include "rs_graphics.rsh"
static rs_allocation layer;
static uint32_t dimX;
static uint32_t dimY;
void setLayer(rs_allocation layer1) {
    layer = layer1;
}
void setBitmapDim(uint32_t dimX1, uint32_t dimY1) {
    dimX = dimX1;
    dimY = dimY1;
}
static float BlendOverlayf(float base, float blend) {
    return (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)));
}
static float3 BlendOverlay(float3 base, float3 blend) {
    float3 blendOverLayPixel = {BlendOverlayf(base.r, blend.r), BlendOverlayf(base.g, blend.g), BlendOverlayf(base.b, blend.b)};
    return blendOverLayPixel;
}
uchar4 __attribute__((kernel)) overlay(uchar4 in, uint32_t x, uint32_t y) {
    float4 inPixel = rsUnpackColor8888(in);
    uint32_t layerDimX = rsAllocationGetDimX(layer);
    uint32_t layerDimY = rsAllocationGetDimY(layer);
    uint32_t layerX = x * layerDimX / dimX;
    uint32_t layerY = y * layerDimY / dimY;
    uchar4* p = (uchar4*)rsGetElementAt(layer, layerX, layerY);
    float4 layerPixel = rsUnpackColor8888(*p);
    float3 color = BlendOverlay(inPixel.rgb, layerPixel.rgb);
    float4 outf = {color.r, color.g, color.b, inPixel.a};
    uchar4 outc = rsPackColorTo8888(outf.r, outf.g, outf.b, outf.a);
    return outc;
}
Renderscript 不使用任何 GPU 或 DSP 内核。这是谷歌故意模糊的文档所助长的一种常见误解。Renderscript 曾经有一个 OpenGL ES 接口,但已被弃用,并且从未用于动画壁纸之外的其他用途。Renderscript 将使用多个 CPU 核心(如果可用),但我怀疑 Renderscript 将被 OpenCL 取代。
查看 Android SDK 中的 Effects 类和 Effects 演示。它展示了如何使用 OpenGL ES 2.0 着色器将效果应用于图像,而无需编写 OpenGL ES 代码。
更新:
当我学会回答问题比提出问题更多时,这真是太棒了,这里就是这种情况。从缺乏答案可以看出,Renderscript 在 Google 之外几乎没有使用,因为它的奇怪架构忽略了 OpenCL 等行业标准,而且几乎不存在关于其实际工作原理的文档。尽管如此,我的回答确实引起了 Renderscrpt 开发团队的罕见回应,其中仅包含一个实际包含有关 renderscript 的任何有用信息的链接 - PowerVR GPU 供应商 IMG 的 Alexandru Voica 撰写的这篇文章:
那篇文章有一些对我来说是新的好信息。有更多人发表评论,表示 Renderscript 代码在 GPU 上实际运行时遇到困难。
但是,我错误地认为 Google 不再开发 Renderscript。尽管我声明“Renderscript 不使用任何 GPU 或 DSP 内核”。直到最近,情况都是如此,我了解到,从果冻豆版本之一开始,这种情况已经发生了变化。如果 Renderscript 开发人员之一能够解释这一点,那就太好了。或者即使他们有一个公共网页来解释或列出实际支持哪些 GPU 以及如何判断您的代码是否实际上在 GPU 上运行。
我的观点是,Google 最终会用 OpenCL 取代 Renderscript,我不会投入时间用它进行开发。
| 归档时间: | 
 | 
| 查看次数: | 4466 次 | 
| 最近记录: |