渲染脚本渲染在Android上比OpenGL渲染慢很多

2024-05-06

背景:

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

PROBLEM:

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

问题:

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

  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进行图像过滤处理。像这样:

    // 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的overlay过程非常慢,大约需要180ms。这是怎么发生的?

这是我们使用的脚本(pLayScript)的rs内核代码:

#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 代码。

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

UPDATE:

当我学会回答问题比提出问题更多时,这真是太棒了,这里就是这种情况。从缺乏答案可以看出,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 http://withimagination.imgtec.com/index.php/powervr/running-renderscript-efficiently-with-powervr-gpus-on-android

那篇文章有一些对我来说是新的好信息。有更多人发表评论,表示 Renderscript 代码在 GPU 上实际运行时遇到困难。

但是,我错误地认为 Google 不再开发 Renderscript。尽管我声明“Renderscript 不使用任何 GPU 或 DSP 内核”。直到最近,情况都是如此,我了解到,从果冻豆版本之一开始,这种情况已经发生了变化。 如果 Renderscript 开发人员之一能够解释这一点,那就太好了。或者即使他们有一个公共网页来解释或列出 实际上支持哪些 GPU 以及如何判断您的代码是否真正在 GPU 上运行。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

渲染脚本渲染在Android上比OpenGL渲染慢很多 的相关文章

随机推荐

  • 变基后无法推送到分支

    我们使用 git 并有一个 master 分支和开发人员分支 我需要添加一个新功能 然后将提交重新设置为 master 然后将 master 推送到 CI 服务器 问题是 如果我在变基期间发生冲突 我无法在变基完成后推送到我的远程开发人员分
  • 使用 SearchView 后重置操作栏

    我在用着SearchView小部件以在我的应用程序中启用搜索 首次单击搜索图标后 SearchView小部件会扩展到搜索字段 并且应用程序图标旁边会显示 后退 箭头 如果我单击应用程序图标 操作栏将恢复到初始状态 没有 后退 箭头 并且Se
  • 如何在 R 中使用相对路径从 mac 上的目录读取数据?

    我正在编写需要同时适用于 Mac 和 Windows 用户的代码 所有用户的计算机上都有 google 驱动器目录的本地副本 我有一段代码可以自动将工作目录设置为源文件位置 我们将此目录称为 directory1 在directory1 中
  • 用户输入时的空闲时间

    我遇到的问题是一个搜索函数 它应该调用我的doSearch 用户在我的系统中停止输入至少 100 毫秒后的方法 input q field 我试图通过使用这个逻辑来实现这一点answer https stackoverflow com a
  • 检测“文件下载”弹出窗口何时关闭

    我有一个网页 用 JSF 制作 其中一些链接允许用户获取 PDF 文件 当用户点击这样的链接时 会显示一个等待弹出窗口 它是一个模式面板 因为 PDF 的生成可能很长 并且一旦创建文件 IE 就会显示 文件下载 弹出窗口 建议 打开 保存
  • 从 GetLastError() 函数返回的错误代码中获取文本

    我需要获取从 GetLastError 函数获得的错误代码的文本 我看到了一些示例 但我想要一个获取代码并返回字符串的函数 谢谢大家 我猜你想要这样的东西 DWORD dwLastError GetLastError TCHAR lpBuf
  • RxJava - 链接请求和更新 UI

    我遇到的问题是这样的 我需要向服务器执行几个请求 下一个请求取决于前一个请求的结果 它们看起来像这样 缩写 Observable
  • 如何调试(最好在 IDE 中)MSBuild 脚本?

    我们非常广泛地使用 MSBuild 作为我们持续集成过程的一部分 虽然它非常强大 我们几乎可以在其中完成所有构建 测试和部署 利用一些自定义任务 我们发现使用标签对其进行调试是一种痛苦 并且不能总是为我们提供足够的信息 我发现 http w
  • 调用事件,h(args) 与 EventName?.Invoke()

    我总是这样调用事件 void onSomeEvent string someArg var h this EventName if h null h this new MyEventArgs someArg 今天 VS 2015 告诉我这可
  • 为什么 getSession() 在短时间内间隔的后续请求中不返回相同的会话?

    我正在发送一个 getJSON HTTP GET 请求两次 使用不同的数据 一次又一次 假设我们有 request1 和 request2 我可以在 FF 和 Chrome 的开发者工具中看到我有相同的cookie JSESSIONID F
  • 使用 leaflet.js 在点周围添加设定大小的正方形多边形

    有点奇怪 希望有人能帮忙 在传单中 一旦用户输入了纬度 经度并向地图添加了一个点 我希望能够在该点周围添加一个 10 公里的正方形 我尝试四处寻找计算方法来找到 x 公里外的正方形角点 但没有挖出任何东西 但肯定有更简单的方法 有人有想法吗
  • 如何在 Django 中创建多选框?

    我正在尝试创建多选框字段来自姜戈选择 2 https github com applegrew django select2库如下图所示 我使用了下一个代码 但它返回简单的选择多个小部件 我想我忘了补充一些东西 我的错误在哪里 有人可以告诉
  • 使用 stringstreams 将字符串转换为 __uint128_t

    我正在尝试从字符串中提取不同类型的数据 void readHeader char buf BUFFSIZE std istringstream hdr buf uint128 t id client hdr gt gt id client
  • C++:初始化结构体并设置函数指针

    我正在尝试使用函数指针初始化结构 但是除非使用全局函数完成 否则我很难这样做 以下代码有效 float tester float v return 2 0f v struct MyClass Example typedef float My
  • 为什么 Visual Studio 2019 不会运行我的单元测试?

    我在 VS2019 中看到 NUnit 测试的一些非常奇怪的行为 而相同的解决方案在 VS2017 中运行良好 我的脑海里有几个 NUnit 测试项目 在安装了 NUnit Runner 扩展的 VS2017 中 我可以在 测试资源管理器
  • 使用 java 执行 Matlab 函数

    我正在编写一个应用程序 它使用 matlab 进行图像处理 然后使用 Java 接口显示结果 由于某些原因 我必须同时使用 Java 和 Matlab 如何在java中使用matlab函数 如何创建和访问界面 MATLAB控制 http m
  • 有没有办法通过 Outlook API 获取建议的联系人?

    我目前正在开发一个应用程序来获取我的 Microsoft 帐户中的联系人 问题是 与 Google 不同 当我向新联系人发送电子邮件或从新联系人接收电子邮件时 该电子邮件不会复制到 我的联系人 中 因此我无法通过该电子邮件https out
  • 如何修复 Visual Studio Code 终端中的“分段错误”错误?

    在 Windows 10 上 我安装了 Visual Studio Code 当我打开终端 Git Bash 并输入less watch compiler 我收到错误 分段故障 但是如果我转到 Git Bash 终端本身 在 Visual
  • 重新创建 Siri 按钮发光动画

    有没有办法复制 Siri 按钮发光动画 它看起来绝对华丽 但我现在不知道如何开始 是否有在线预格式化的旋转PNG 或者是用CoreAnimation完成的 我相信 Siri 动画是用 CAEmitterLayer 和 CAEmitterCe
  • 渲染脚本渲染在Android上比OpenGL渲染慢很多

    背景 我想根据Android相机应用程序的代码添加实时滤镜 但Android相机应用程序的架构是基于OpenGL ES 1 x 我需要使用着色器来自定义我们的过滤器实现 然而 将相机应用程序更新到OpenGL ES 2 0太困难了 然后我必