gpt4 book ai didi

android - 渲染脚本渲染比 Android 上的 OpenGL 渲染慢很多

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:05:37 26 4
gpt4 key购买 nike

背景:

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

问题:

我已经通过渲染脚本编写了一个简单的过滤器演示。它表明 fps 比通过 OpenGL 实现它要低得多。大约 5 fps 与 15 fps。

问题:

  1. Android 官方 offsite 说:RenderScript 运行时将跨设备上可用的所有处理器并行工作,例如多核 CPU、GPU 或 DSP,让您专注于表达算法而不是调度工作或负载均衡。那为什么render script执行的比较慢呢?

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

代码详情:

嗨,我和提问者在同一个团队。我们想编写一个基于渲染脚本的实时滤镜相机。在我们的测试演示项目中,我们使用了一个简单的过滤器:一个添加了覆盖过滤器 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) 根据我们的time-log,使用intrinsic script的YUV转RGBA的过程非常快,大约需要6ms;但是使用scriptC的覆盖过程很慢,大约需要180ms。这是怎么发生的?

这里是我们使用的ScriptC(mLayerScript)的rs-kernal代码:

#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 的接口(interface),但是已经被弃用并且除了动画壁纸之外从未被用于太多。 Renderscript 将使用多个 CPU 内核(如果可用),但我怀疑 Renderscript 将被 OpenCL 取代。

查看 Android SDK 中的 Effects 类和 Effects 演示。它展示了如何在不编写 OpenGL ES 代码的情况下使用 OpenGL ES 2.0 着色器将效果应用于图像。

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

更新:

当我回答一个问题比问一个问题学到更多时,这真是太好了,这里就是这种情况。从缺乏答案可以看出,Renderscript 几乎没有在 Google 之外使用,因为它的奇怪架构忽略了 OpenCL 等行业标准,并且几乎不存在关于它如何实际工作的文档。尽管如此,我的回答确实引起了 Renderscrpt 开发团队的罕见回应,其中只有一个链接实际上包含有关 renderscript 的任何有用信息——这篇由 PowerVR GPU 供应商 IMG 的 Alexandru Voica 撰写的文章:

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

那篇文章有一些很好的信息,这对我来说是新的。有更多人在 GPU 上实际运行 Renderscript 代码时遇到问题,他们发表了评论。

但是,我认为 Google 不再开发 Renderscript 是错误的。尽管我声明“Renderscript 不使用任何 GPU 或 DSP 内核”。直到最近才如此,我了解到这已经改变了 Jelly Bean 的一个版本。如果其中一位 Renderscript 开发人员能够解释这一点,那就太好了。或者即使他们有一个公共(public)网页来解释那个或那个列表实际支持哪些 GPU,以及如何判断您的代码是否确实在 GPU 上运行。

我的观点是 Google 最终会用 OpenCL 取代 Renderscript,我不会花时间用它进行开发。

关于android - 渲染脚本渲染比 Android 上的 OpenGL 渲染慢很多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21774211/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com