【问题标题】:2D array in constant buffer常量缓冲区中的二维数组
【发布时间】:2019-06-30 23:28:47
【问题描述】:

我试图将一个 2D 浮点数组传递给一个常量缓冲区:

//In the shader:
    cbuffer myBuffer
    {
        other buffer elements
        .
        .
        float myArray[16][16];
    };

//In the CPU:
    struct  myBuffer_struct
    {
        other buffer elements
        .
        .
        float myArray[16][16];
    };

但是我在处理填充时遇到了很多问题。我尝试使用

float4[大小/4][大小]

在我的 cbuffer 和许多其他类型组合中,但我无法以任何方式通过索引访问我的数组。这样做的正确方法是什么?

谢谢。

【问题讨论】:

  • 使用适当的编译器选项摆脱填充。如果您的 struct 需要进行字节打包,请使用 #pragma 或您的编译器使用的任何方式指定它。
  • 我很困惑为什么在包含单个成员的结构中会有填充,其对齐要求小于其自身的大小。数组元素之间不能有填充。
  • 我的结构中有更多元素,而不仅仅是二维数组
  • 对于 cbuffer 填充,所有字段的详细信息(大小和顺序)都很重要,因为它们相互依赖。你能发布你对这两个声明的完整定义吗?

标签: c++ directx-11 hlsl


【解决方案1】:

我遇到了这个问题,它基本上归结为缓冲区的对齐方式。您的 HLSL cbuffer 定义肯定会与您在结构中定义的内容不同。

对齐可能沿着 16 字节(4 个浮点数)对齐。在我的代码中,我将 4 个浮点数写入缓冲区。如下所示,因为 cbuffer 中的数组对齐方式不同。

         for (int i = 0; i < 8; i++)
        {
            stream.Write<float>(m_waveLengths[i] ); 
            stream.Write<float>(m_waveSpeeds[i] );
            stream.Write<float>(m_amplitudes[i] ); 
            stream.Write<float>(m_steepness[i]); 
        }

为了阅读本文,我使用了 float4 数组定义。

// hlsl definition
float4 Wave[8];  

然后我将相关项目引用为 Wave[0].x、Wave[0].y、Wave[0].z、Wave[0].w

如果我不这样打包,内存对齐会使缓冲区大 4 倍。这是因为在 HLSL 代码中,缓冲区定义似乎沿 16 字节边界(4 x 浮点数)对齐数组的每个元素。因此,我将 4 个数组交织成 1 个数组,并使用 float4 的属性来引用它。

因为 float waveLengths[8] 的对齐意味着我必须像这样将它写入缓冲区:

   for (int i = 0; i < 8; i++)
        {
            stream.Write<float>(m_waveLengths[i] ); 
            stream.Write<float>(0.0f);
            stream.Write<float>(0.0f); 
            stream.Write<float>(0.0f); 
        }

出于某种原因(我可能没有设置某个 HLSL 编译器指令),在 Cbuffer 中使用数组有一些怪癖,它会将每个元素填充到 16 字节边界。

因此,对于您的 float myArray[16][16],我假设您查看对齐方式,您可能必须以类似的方式为此写入缓冲区,在每个元素之后填充 12 个字节大批。我相信有人会用正确的编译器指令来解决这个怪癖,我刚刚解决了这个问题,你的问题看起来和我的问题很相似。

【讨论】:

    猜你喜欢
    • 2019-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    • 1970-01-01
    • 1970-01-01
    • 2014-10-30
    • 1970-01-01
    相关资源
    最近更新 更多