渲染脚本渲染比Android上的OpenGL渲染慢得多

背景:

我想添加基于Android相机应用程序代码的实时滤镜。 但Android相机应用程序的体系结构基于OpenGL ES 1.x. 我需要使用着色器来定制我们的过滤器实现。 但是,将相机应用程序更新为OpenGL ES 2.0太困难了。 然后,我必须找到一些其他方法来实现实时滤镜而不是OpenGL。 我决定在研究后使用渲染脚本。

问题:

我用渲染脚本编写了一个简单过滤器的演示。 它显示fps远低于OpenGL的实现。 大约5 fps vs 15 fps。

问题:

  • Android官方现场表示:RenderScript运行时将并行处理设备上可用的所有处理器(如多核CPU,GPU或DSP)的工作,使您可以专注于表达算法,而不是调度工作或负载平衡。 那么为什么渲染脚本执行速度较慢?

  • 如果渲染脚本不能满足我的要求,有没有更好的方法?

  • 代码详情:

    嗨,我和提问者在同一个团队中。 我们想写一个基于渲染脚本的实时滤镜相机。 在我们的测试演示项目中,我们使用了一个简单的过滤器:添加了overlay-filter ScriptC脚本的YuvToRGB IntrinsicScript。 在OpenGL版本中,我们将相机数据设置为纹理,并使用着色器进行图像过滤处理。 喜欢这个:

        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内核。 这是Google故意模糊文档鼓励的常见误解。 Renderscript曾经有一个OpenGL ES的接口,但已经被弃用,并且从未被用于超过动画壁纸。 Renderscript将使用多个CPU内核(如果可用),但我怀疑Renderscript将被OpenCL取代。

    查看Android SDK中的效果类和效果演示。 它演示了如何使用OpenGL ES 2.0着色器将效果应用于图像,而无需编写OpenGL ES代码。

    http://software.intel.com/en-us/articles/porting-opengl-games-to-android-on-intel-atom-processors-part-1

    更新:

    当我更多地回答一个问题而不是问一个问题时,这真是太好了,这里就是这种情况。 你可以从缺乏答案中看出,Renderscript很难在谷歌之外使用,因为它的奇怪架构忽略了像OpenCL这样的行业标准以及几乎不存在的关于它如何工作的文档。 尽管如此,我的回答确实引起了Renderscrpt开发团队的罕见回应,该团队只包含一个实际包含有关renderscript的有用信息的链接 - 本文由Alexandru Voica在IMG,PowerVR GPU供应商提供:

    http://withimagination.imgtec.com/index.php/powervr/running-renderscript-efficiently-with-powervr-gpus-on-android

    那篇文章有一些对我来说是新的很好的信息。 有更多的人在Renderscript代码实际在GPU上运行时遇到麻烦。

    但是,我认为Renderscript不再被Google开发是不正确的。 尽管我声明“Renderscript不使用任何GPU或DSP内核”。 直到最近才成立,我知道这已经发生了改变,因为Jelly Bean的发布。 如果其中一位Renderscript开发人员可以解释这一点,那就太棒了。 或者即使他们有一个公共网页可以解释或列出哪些GPU实际上受支持,并且如何确定您的代码实际上是否在GPU上运行。

    我的看法是Google最终会用OpenCL取代Renderscript,我不会花时间去开发它。

    链接地址: http://www.djcxy.com/p/18991.html

    上一篇: Render script rendering is much slower than OpenGL rendering on Android

    下一篇: Match legend to axes objects