【发布时间】:2020-04-22 17:31:12
【问题描述】:
在我正在制作的一个非常基本的 D3D11 引擎中如何组织常量缓冲区时遇到了一些麻烦。
我的主要问题是:最大的性能损失发生在哪里?使用 Map/Unmap 更新缓冲区数据或绑定 cbuffers 时?
目前,我正在为一种“shader-wrapper”类选择以下两种实现:
持有14个ID3D11Buffer*s的数组
class VertexShader
{
...
public:
Bind(context)
{
// Bind all 14 buffers at once
context->VSSetConstantBuffers(0, 14, &m_ppCBuffers[0]);
context->VSSetShader(pVS, nullptr, 0);
}
// Set the data for a buffer in a particular slot
SetData(slot, size, pData)
{
D3D11_MAPPED_SUBRESOURCE mappedBuffer = {};
context->Map(buffers[slot], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedBuffer);
memcpy(mappedBuffer.pData, pData, size);
context->Unmap(buffers[slot], 0);
}
private:
ID3D11Buffer* buffers[14];
ID3D11VertexShader* pVS;
}
这种方法将使着色器将所有 cbuffers 绑定在一个批次中,每批 14 个。如果着色器的 cbuffers 注册到 b0、b1、b3,则数组看起来像 -> [cb|cb|0|cb|0| 0|0|0|0|0|0|0|0|0]
知道如何绑定自身的常量缓冲区包装器
class VertexShader
{
...
public:
Bind(context)
{
// all the buffers bind themselves
for(auto cb : bufferMap)
cb->Bind(context);
context->VSSetShader(pVS, nullptr, 0);
}
// Set the data for a buffer with a particular ID
SetData(std::string, size, pData)
{
// table lookup into bufferMap, then Map/Unmap
}
private:
std::unordered_map<std::string, ConstantBuffer*> bufferMap;
ID3D11VertexShader* pVS;
}
这种方法会将“ConstantBuffers”保存在哈希表中,每个人都知道它绑定到哪个插槽以及如何将自己绑定到管道。我必须为每个 cbuffer 单独调用 VSSetConstantBuffers(),因为 ID3D11Buffer*s 不再是连续的,但组织更友好,浪费的空间也更少。
您通常如何组织 CBuffer、Shader、SRV 等之间的关系?不是在寻找万能的解决方案,而是从希望比我更有经验的人那里了解一些一般性建议和内容
另外,如果@Chuck Walbourn 看到了这一点,我是你工作的粉丝,并且在这个项目中使用了 DXTK/WiCTextureLoader!
谢谢。
【问题讨论】:
-
“我的主要问题是:最大的性能损失发生在哪里?” - 你应该分析你的代码并向你的分析器询问这个问题。
标签: directx-11 direct3d direct3d11