【问题标题】:sizeof custom struct for compute shader stride用于计算着色器步幅的自定义结构的 sizeof
【发布时间】:2019-11-02 02:47:28
【问题描述】:

我正在尝试使用 Unity 编写一个计算着色器,为体素地形生成网格数据(顶点、法线、uvs)。因此,我有一个自定义结构定义如下:

[StructLayout(LayoutKind.Sequential, Pack = 0)]
private struct VertexData
{
    public Vector3 position;

    public Vector3 normal;

    public Vector2 uv;
}

然后,我正在为 ComputeShader 创建一个 ComputeBuffer,如下所示:

vecterDataCBuf = new ComputeBuffer(ChunkSize * ChunkSize * ChunkSize, sizeof(VertexData));

我收到 CS0233 错误,表明我无法在我的自定义结构上使用 sizeof 运算符来为计算缓冲区提供步幅,尽管我添加了打包属性。

所以我的问题是,如何在不进行硬编码的情况下获得结构的大小?谢谢。

【问题讨论】:

  • 我相信 unity 有一个特定的辅助方法:UnsafeUtility.SizeOf<T>()。要么这样,要么您必须使用 unsafe 标志进行编译才能使用 sizeof 运算符。
  • @mikez 那seems to be correct。这不应该是一个答案吗?
  • @CamiloTerevinto 我几乎不是统一的专家,所以这可能不是正确的方法。我在 google 上相对较快地找到了它,但是在他们的 github repo 中查看示例代码,他们几乎总是使用 sizeof 或 System.Runtime.InteropServices.Marshal.SizeOf。
  • 有兴趣知道!谢谢。
  • 我遇到了这个问题,我也在我的结构中使用using System.Runtime.InteropServices;public static int SizeOf = Marshal.SizeOf(typeof(MyStructType));。它正在编辑器中工作,尚未尝试构建。我也没有收到不安全的警告。考虑到我可以手动计算它,这似乎有点矫枉过正,但当我积极更改结构时,它对开发人员来说非常方便。

标签: c# unity3d


【解决方案1】:

sizeof 仅适用于预定义类型,除非您处于 unsafe 上下文中。 From the reference on sizeof:

下表显示了替换具有某些内置类型作为操作数的 sizeof 表达式的常量值。 [...] 对于所有其他类型,包括结构,sizeof 运算符只能在不安全的代码块中使用。

因此,请将您的电话转入unsafe,例如:

int sizeOfVertexData;
unsafe
{
    sizeOfVertexData = sizeof(VertexData);
}

您还必须启用不安全代码。 In Unity it's apparently a checkbox.

【讨论】:

  • 感谢您的帮助。但是它是如何使代码不安全的呢?平台/编译器/硬件之间的大小可能不同?我假设需要 unsafe 关键字是有充分理由的。
  • @Virus721 此答案上的文档链接指向here。我建议你熟悉一下
  • @Virus721 对于普通的 C# 应用程序,sizeof 最常见的用途涉及指针或读/写内存。通常,C#/.NET 会为您管理内存,从而防止多种安全漏洞,但指针操作绕过了其中的一些保护。代码被称为unsafe 并不是因为它一定很危险,而是因为它可能是危险的(有意或无意地通过错误)。但是,对于这种情况,鉴于您只是使用 sizeof,它可能没问题。
【解决方案2】:

您可以通过添加每个属性大小来计算结构的总大小。

一个 Vector3 相当于 3 个浮点数。 一个 Vector2 相当于 2 个浮点数。

//int stride  = sizeof(position) + sizeof(normal) + sizeof(uv)
//int stride  = sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector2)
int stride = sizeof(float) * 3 + sizeof(float) * 3 + sizeof(float) * 2

你不需要不安全的东西。

【讨论】:

  • 这个,特别是在格式方面的缺点,是仅边界代码。请扩展您的解释并使用它来帮助识别它们实际上是一种解释。 stackoverflow.com/editing-help
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-06
  • 2021-04-29
  • 1970-01-01
  • 2011-02-09
  • 2017-03-11
  • 2018-05-07
相关资源
最近更新 更多