【问题标题】:Maximum triangle count in RenderScriptRenderScript 中的最大三角形计数
【发布时间】:2012-05-30 21:58:43
【问题描述】:

我编写了一个快速应用程序来感受 RenderScript 的限制,并发现当达到大约 65,000 个三角形时,系统根本不会绘制任何额外的三角形。例如,如果我创建一个包含 70,000 个三角形的圆柱体,则圆柱体中缺少一个楔形,对应于超过 ~65,000 个计数的三角形。三角形带有纹理,为了便于编写应用程序,我只使用了TriangleMeshBuilder 类,因此没有进行真正的优化,例如使用 trifans 或 tristrips。硬件是三星 Galaxy Nexus。 LogCat 报告的堆大小约为 15MB,其中 3% 可用。我没有收到有关图形系统或 RenderScript 的错误或警告。

谁能解释三角形被丢弃的原因?我是否处于 RenderScript 正常处理的硬件限制?

更新发生在三星 Galaxy Nexus (4.0.3)、三星 Galaxy Tab 7.0+ (3.2) 和摩托罗拉 Xoom (3.2) 上。全部在大约 65,000 个三角形的同一点上。这些设备中的每一个都有不同的 GPU。

更新 2 针对 Steve Blackwell 的见解,我有一些额外的想法。

第 710-712 行确实将 int 索引向下转换为 short,因此正如史蒂夫指出的那样,65536 变为 0。此外,第 757 行的“演员表”与其说是演员表,不如说是告诉 RenderScript 最终将发送给它的二进制数据的格式。 RenderScript 要求将所有数据打包到称为 Allocation 的 RenderScript 特定数据类型中,以便从 Java 移动到 RenderScript 运行时,这需要了解数据结构。根据 Steve 认为这是一个错误的观点,第 757 行通知 RenderScript 将索引数据视为short(无符号 16 位),但它会发送一个 32 位有符号值(由于缺少检查和处理无符号,然后只使用低 16 位,因此为什么我们在低于此阈值时绘制一些东西,而当我们超过时,三角形连接回第一个索引)。

子类化TriangleMeshBuilder 看看我是否可以让它接受这些值作为整数来增加这个限制不起作用,这让我相信在我们无法访问的深层代码的某个地方,还有一个额外的参考未签名的短裤。看起来唯一的解决方法是按照史蒂夫的建议添加额外的顶点缓冲区,这很容易通过现有的Mesh.AllocationBuilder 类完成。我还将在开发者环聊中向 Google 提出,以确定这实际上是错误还是故意的。

【问题讨论】:

  • 你在其他设备上试过了吗?

标签: android renderscript


【解决方案1】:

我对 RenderScript 几乎一无所知,所以我不知道这是否是一些固有的限制、硬件问题或与 TriangleMeshBuilder 相关的问题,但我敢打赌,在编号 65535 之后你的三角形已经用完了。

这是一个幻数,因为它是无符号 16 位整数的最大值。 (Wikipedia)

我怀疑代码中的某处有一个 unsigned short 保存三角形的数量。它不会出现在 Java 代码中,因为 Java 没有无符号值。并且限制可能不是硬件,因为 CPU 寄存器/路径 >= 32 位。所以我会检查 TriangleMeshBuilder。

编辑:

这是line 553 上的一个很棒的发现。每个索引的值都必须适合shortline 710-712 似乎正在发生低迷。

我假设你打电话给addTriangle()。该函数需要三个ints,然后显式转换为short。我认为这是一个错误,因为向下转换是静默发生的,这不是您对函数签名的期望。

line 768 上,虚假数据被传递给Allocation.copy1DRangeFromUnchecked()。我没有一直遵循它,但我想在某些时候,那些有符号的值会被强制转换为无符号:-32768 到 -1 会变回 32768 到 65535。所以把索引变成负数看起来很糟糕,但它只是重新解释相同的数据,这并不是真正的问题。

真正的问题始于您发送 65536 之类的值。当 65536 转换为 short 时,它变成 0。这是真正的数据丢失。现在您指的是不同的索引,而强制转换为 unsigned 并不能解决它。

真正的问题在于copy1DRangeFromUnchecked() 是一个重载函数,并且是overloads takes an int[] 之一,所以这些都不是问题。

对于解决方法,我想您可以继承 TriangleMeshBuilder 并覆盖成员变量 mIndexData[] 和方法 addTriangle()。或者,也许您可​​以使用多个顶点缓冲区。或者在某个地方提交错误报告?无论如何,有趣的问题。

【讨论】:

  • 它不能在 TriangleMeshBuilder 中,因为那也是 Java,但由于 RenderScript 是用 C99 编写的,因此很可能是这种情况。没有意识到我接近那个阈值,我感到很傻,特别是因为它让我意识到我低于 32 位限制。我将尝试查看 C 代码,看看是否有任何弹出。
  • 我刚刚查看了相关 RenderScript 数据类型的类型定义,它们都使用无符号 32 位整数。最初我会怀疑(如果我错了,请纠正我)这不是问题,但是我无法查看 RenderScript 的实际源代码(只是头文件)。
  • 我真的不知道从这里去哪里。如果您有想要显示的代码,或者您可以指出您正在使用的示例,这可能会有所帮助,但我对 RenderScript 有点不满意。
  • 制作相关网格的代码可以在我对这个问题的回答中找到:stackoverflow.com/questions/10732813/…。对于每个“切片”,您最终会得到 4 个三角形。短整数限制将是 16384 片。不幸的是,在 Google 的一位 RenderScript 工程师介入之前,我无法确定 RenderScript 源中是否存在无符号短路。
  • 鉴于我没有从谷歌收到相反的信息,这似乎是问题的最合理原因(由于其硬件独立性),我倾向于同意你的原因,所以这里还有一些要点。谢谢。
【解决方案2】:

这可能是因为 OpenGL ES 只允许 short 元素索引,而不是 int。来源:http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-2.1:-Buffers-and-Textures.html(搜索“OpenGL ES”)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多