在常量缓冲区中打包 HLSL 浮点数组?

Ben*_*Goh 5 directx hlsl directx-11 vertex-shader

人们。

我在通过constant buffer浮点数组传递给顶点着色器(HLSL)时遇到问题。我知道由于 HLSL 打包规则,下面数组中的每个“浮点数”都单独获得一个 16 字节的插槽(空间相当于 float4):

// C++ struct
struct ForegroundConstants
{
    DirectX::XMMATRIX transform;
    float bounceCpp[64];
};


// Vertex shader constant buffer
cbuffer ForegroundConstantBuffer : register(b0)
{
    matrix transform;
    float bounceHlsl[64];
};
Run Code Online (Sandbox Code Playgroud)

(不幸的是,这里的简单解决方案不起作用,在我进行更改后没有绘制任何内容)

而C ++数据被传递时,由于包装规则他们得到间隔开,使得每个“浮动”中bounceCpp C ++阵列中进入一个16字节的空间中的所有本身bounceHlsl阵列。这导致了类似于以下内容的警告:

ID3D11DeviceContext::DrawIndexed:Vertex Shader 单元的 slot 0 处的 Constant Buffer 的大小太小(提供 320 字节,至少 1088 字节,预期)。这是可以的,因为越界读取被定义为返回 0。开发人员也可能知道无论如何都不会使用丢失的数据。如果开发人员实际上打算为着色器期望绑定足够大的常量缓冲区,这只是一个问题。

正如此处此处所指出的,建议以这种方式重写 HLSL 常量缓冲区:

cbuffer ForegroundConstantBuffer : register(b0)
{
    matrix transform;
    float4 bounceHlsl[16]; // equivalent to 64 floats.
};

static float temp[64] = (float[64]) bounceHlsl;

main(pos : POSITION) : SV_POSITION
{
    int index = someValueRangeFrom0to63;
    float y = temp[index];

    // Bla bla bla...
}
Run Code Online (Sandbox Code Playgroud)

但这不起作用(即 ID3D11Device1::CreateVertexShader 永远不会返回)。我正在针对Shader Model 4 Level 9_1编译东西,你能发现我在这里做错了什么吗?

提前致谢!:)

问候,本

小智 4

一种解决方案(尽管不是最佳方案)是将浮点数组声明为

float4 bounceHlsl[16];
Run Code Online (Sandbox Code Playgroud)

然后像这样处理索引

float x = ((float[4])(bounceHlsl[i/4]))[i%4];
Run Code Online (Sandbox Code Playgroud)

其中 i 是您需要的索引。

  • 但要小心,它可能效率低下:https://geidav​​.wordpress.com/2013/03/05/hidden-hlsl-performance-hit-accessing-unpadded-arrays-in-constant-buffers/ (2认同)