无法找出 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_DYNAMIC
和 D3D11_CPU_ACCESS_WRITE
并删除 D3D11_BIND_UNORDERED_ACCESS
.
如果您想通过在 HLSL 着色器中声明 RWStructuredBuffer
来从 GPU 写入缓冲区,则保留 D3D11_BIND_UNORDERED_ACCESS
但删除 D3D11_CPU_ACCESS_WRITE
并更改 D3D11_USAGE_DYNAMIC
到 D3D11_USAGE_DEFAULT
。当然绑定之前必须先创建无序访问视图
还有一件事,要像您一样在着色器中使用它,您需要创建着色器资源视图:
device->CreateShaderResourceView(buffer.Get(), nullptr, &srv);
其中 srv 是 Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>
或 ID3D11ShaderResourceView*
。然后使用 *SetShaderResources
绑定它。也许您已经这样做了,但提及它也无妨。
您也不需要像常量缓冲区那样将 ByteWidth 设为 16 的倍数。你可以只写
desc.ByteWidth = sizeof(T) * num;
P.S。如果你还没有,你应该启用调试层,因为它对调试这类问题很有帮助。
我正在尝试创建一个 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_DYNAMIC
和 D3D11_CPU_ACCESS_WRITE
并删除 D3D11_BIND_UNORDERED_ACCESS
.
如果您想通过在 HLSL 着色器中声明 RWStructuredBuffer
来从 GPU 写入缓冲区,则保留 D3D11_BIND_UNORDERED_ACCESS
但删除 D3D11_CPU_ACCESS_WRITE
并更改 D3D11_USAGE_DYNAMIC
到 D3D11_USAGE_DEFAULT
。当然绑定之前必须先创建无序访问视图
还有一件事,要像您一样在着色器中使用它,您需要创建着色器资源视图:
device->CreateShaderResourceView(buffer.Get(), nullptr, &srv);
其中 srv 是 Microsoft::WRL::ComPtr<ID3D11ShaderResourceView>
或 ID3D11ShaderResourceView*
。然后使用 *SetShaderResources
绑定它。也许您已经这样做了,但提及它也无妨。
您也不需要像常量缓冲区那样将 ByteWidth 设为 16 的倍数。你可以只写
desc.ByteWidth = sizeof(T) * num;
P.S。如果你还没有,你应该启用调试层,因为它对调试这类问题很有帮助。