无法找出 DirectX11 中的 StructuredBuffers

Unable to figure out StructuredBuffers in DirectX11

我正在尝试创建一个 StructuredBuffer 以尝试在 D3D11 中制作一些骨骼动画。我在骨架部分取得了坚实的进展,但是创建一个 StructuredBuffer 让我感到难过,而且我在网上搜索时似乎找不到任何可靠的建议。

目前我只是猜测如何在着色器中使用它,不知道如何将数据发送到 GPU。我尝试修改用于 ConstantBuffers 的模板函数(我将在下面显示代码块),但很快就进入了死胡同。

该项目主要是用 C++ 制作的,还有一些外部 C 库。

// Template function to create a constant buffer (This works as intended)
template<class T>
bool createBuffer(ID3D11Device* device, ID3D11Buffer*& buffer)
{
    T emptyValues;
    D3D11_BUFFER_DESC desc;
    desc.ByteWidth = sizeof(T) + (16 - sizeof(T) % 16);
    desc.Usage = D3D11_USAGE_DYNAMIC;
    desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    desc.MiscFlags = 0;
    desc.StructureByteStride = 0;

    D3D11_SUBRESOURCE_DATA data;
    data.pSysMem = &emptyValues;
    data.SysMemPitch = 0;
    data.SysMemSlicePitch = 0;

    HRESULT hr = device->CreateBuffer(&desc, &data, &buffer);
    return !FAILED(hr);
};
// Modified template function to create a structured buffer, this always fails
template<class T>
bool createStructuredBuffer(ID3D11Device* device, ID3D11Buffer*& buffer, const T* dataAdress, unsigned int num)
{
    unsigned int stride = sizeof(T);
    unsigned int byteWidth = stride * num + (16 - sizeof(T) % 16);

    D3D11_BUFFER_DESC desc;
    desc.ByteWidth = byteWidth;
    desc.Usage = D3D11_USAGE_DYNAMIC;
    desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
    desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; // D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS ?
    desc.StructureByteStride = stride;

    D3D11_SUBRESOURCE_DATA data;
    data.pSysMem = dataAdress;
    data.SysMemPitch = 0;
    data.SysMemSlicePitch = 0;

    HRESULT hr = device->CreateBuffer(&desc, &data, &buffer);
    return !FAILED(hr);
}
// This is what I've gathered on how to use the StructuredBuffer in a shader, but this could also be completely wrong since I really have no idea what I'm doing with them.
StructuredBuffer<matrix> boneTransformation;

cbuffer constantBuffer : register(bX)
{
    int StructuredBufferSize;
}

type_a main(type_b input)
{
    int someInt = /*A number between 0 and StructuredBufferSize*/;
    doSomethingWith(boneTransformation[someInt]);
}

您不能同时拥有 D3D11_BIND_UNORDERED_ACCESS 绑定标志和 D3D11_USAGE_DYNAMIC

如果您想通过映射缓冲区从 CPU 端写入缓冲区,请保留 D3D11_USAGE_DYNAMICD3D11_CPU_ACCESS_WRITE 并删除 D3D11_BIND_UNORDERED_ACCESS.

如果您想通过在 HLSL 着色器中声明 RWStructuredBuffer 来从 GPU 写入缓冲区,则保留 D3D11_BIND_UNORDERED_ACCESS 但删除 D3D11_CPU_ACCESS_WRITE 并更改 D3D11_USAGE_DYNAMICD3D11_USAGE_DEFAULT。当然绑定之前必须先创建无序访问视图

还有一件事,要像您一样在着色器中使用它,您需要创建着色器资源视图:

device->CreateShaderResourceView(buffer.Get(), nullptr, &srv);

其中 srv 是 Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>ID3D11ShaderResourceView*。然后使用 *SetShaderResources 绑定它。也许您已经这样做了,但提及它也无妨。

您也不需要像常量缓冲区那样将 ByteWidth 设为 16 的倍数。你可以只写

desc.ByteWidth = sizeof(T) * num;

P.S。如果你还没有,你应该启用调试层,因为它对调试这类问题很有帮助。