【问题标题】:How to get around the performance issues with Buffer.put() and Android OpenGL如何解决 Buffer.put() 和 Android OpenGL 的性能问题
【发布时间】:2011-03-27 02:53:49
【问题描述】:

这通常是一个 Java 问题,但在这种特殊情况下,我在 Android 中为 OpenGL 使用顶点数组。要使用这个基本的 GL 系统,您必须在本地分配模式下使用 Java 的 Buffer 系统。这在 Java 上非常慢。我整个应用程序大约 40-50% 的时间都花在了 buffer.put() 中。

在使用 Java 时有什么方法可以加快速度(即不使用本机 sdk)?

【问题讨论】:

  • 您多久编写一次值?应该是您在启动时所做并忘记的事情。
  • 为了解决 Java 的 GC 不断地破坏对象的问题,我使用一个顶点缓冲区来处理我的许多网格。由于我的程序中有很多网格,每个网格有一个对象会导致 GC 发疯。而且 GC 收集在较旧的 Android 手机上非常缓慢。当然,我会尽可能地重用这些值。

标签: android performance opengl-es buffer


【解决方案1】:

我在集成Java和JOGL时也遇到过类似的问题——我的解决方案是在C中管理缓冲区资源,并使用JNI方法将指向缓冲区的指针传递给Java

jobject NewDirectByteBuffer(JNIEnv * env, void * address, jlong capacity); 

在 jni.h 中找到。当您需要将偏移量更新到缓冲区中时,请使用反射手动修改 java.nio.Buffer 中的“地址”字段。如果添加更多元素会导致超出 C 中缓冲区的容量,请在 C 中使用数组列表,并让缓冲区直接指向列表的支持数组。

【讨论】:

  • 非常有趣的解决方案。但是,我想远离任何本机编码。不过我会记住这一点。
【解决方案2】:

一般避免分配。使用缓冲区池并根据需要调整它们。你可以有几个标准大小,最后浪费几个字节来换取性能。此外,在使用 OpenGL 时,您通常不需要每帧都重写缓冲区(除非您进行大量蒙皮或动画?)。通常,你有你的预烘焙数组,使用矩阵变换对象,就是这样。

【讨论】:

  • 分配不是问题。我只在程序启动时分配一次。分配缓冲区的更改(使用 put() 方法)很慢。至于重写缓冲区,我发现在 Android 上的 Java 中,拥有一些改变值的缓冲区比分配数百个单独的缓冲区要好(由于内存消耗)。我正在使用几个缓冲区并根据需要更改其中的值(遗憾的是每一帧)。
  • 这不是一个完整的答案,但它为首先尝试避免此问题提供了最佳建议。所以我给了你赏金和答案(因为它无论如何都是有用的信息)
  • 谢谢!我唯一的其他建议,以真正的“duh”风格,是尽量避免改变每一帧的值?有什么变化?你的网格变形了吗?您能否将更改缓冲区和静态缓冲区分开,并将所有更改的数据保存在这些缓冲区的同一区域内? (例如,=all 在开头)
  • 我使用相同的缓冲区来显示多个项目,并且只使用 GL 转换在屏幕上移动相同的项目。在只移动的情况下,我不重写缓冲区,只是在 gl world 中翻译它们。但是,不能保证每一项都与下一项具有相同的大小(甚至比例),在这种情况下,当且仅当项的大小与前一项不同时,我必须重写缓冲区。
  • 如果你只是翻译它们,不要修改缓冲区 - 只需使用矩阵来变换它们。 (听起来您已经这样做了?)您还有哪些其他修改需要您修改缓冲区?
【解决方案3】:

你唯一能做的就是批量处理你的工作,并希望手机中的实现是体面的,因为惩罚来自锁定和解锁。如果您批量呼叫,驱动程序应该锁定和解锁一次。如果您“自发地”执行此操作,您将一直锁定和解锁,这会给您带来巨大的性能损失。 如果驱动程序不够聪明,只能将缓冲区映射到 ram 一次而不是每次调用,那么最好的办法就是尽量减少 put 的数量。

【讨论】:

  • 驱动程序与 Java 中的本机缓冲区有什么关系?缓慢的部分不是将缓冲区上传到 OpenGL 内存,而是实际的 Java 缓冲区本身。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-10
  • 2021-06-12
  • 1970-01-01
  • 1970-01-01
  • 2011-04-06
  • 1970-01-01
  • 2021-10-24
相关资源
最近更新 更多