DirectX将数组数据复制到常量缓冲区中

时间:2015-10-23 20:29:42

标签: directx-11

如果我们要更新常量缓冲区的结构包含一个向量, 只使用copyMemory或memcpy与struct starting指针和struct的大小,不会复制矢量数据,是不是?

struct PerObjectCB {
XMFLOAT4X4 World;
XMFLOAT4X4 WorldInvTranspose;
XMFLOAT4X4 TexTransform;
Material Mat;
vector<XMFLOAT4X4> BoneTransforms;
};
PerObjectCB Data = {.,.,., ..., {/*BoneTransforms data*/}};
ID3D11Buffer* mBuffer;
ID3D11_BUFFER_DESC desc = {...};
device->CreateBuffer(&desc, 0, &mBuffer);
D3D11_MAPPED_SUBRESOURCE mappedResource;
dc->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
CopyMemory(mappedResource.pData, &Data, sizeof(Data));
dc->Unmap(mBuffer, 0);

我将这些更新常量缓冲区代码放入模板类中,然后我可以使用此类来管理更新常量缓冲区,但是当我遇到动画数据向量时,我使用cout&lt;&lt; sizeof(向量&lt; XMFLOAT4X4&gt; BoneTransforms),无论我在向量中放入多少数据,这个向量的大小总是12,我猜结构只存储向量的起始地址,真正的数据是在其他地方。如果这是真的,我该如何处理?

我是否真的必须放弃我为常量缓冲区管理编写的模板类,并专门为更新数组类型数据编写另一个函数?

1 个答案:

答案 0 :(得分:0)

所以问题是std::vector不是POD(普通旧数据)。

struct PerObjectCB {
XMFLOAT4X4 World;
XMFLOAT4X4 WorldInvTranspose;
XMFLOAT4X4 TexTransform;
Material Mat;
vector<XMFLOAT4X4> BoneTransforms;
};

这将是sizeof(XMFLOAT4X4) * 3 + sizeof(Material) + sizeof(std::vector)。它与BoneTransforms.size() * sizeof(XMFLOAT4X4)没有任何关系。

如果您要在此CB中发送骨骼变换,则需要选择最大骨骼尺寸&#39;

struct PerObjectCB {
XMFLOAT4X4 World;
XMFLOAT4X4 WorldInvTranspose;
XMFLOAT4X4 TexTransform;
Material Mat;
XMFLOAT4X4 BoneTransforms[MAX_BONES];
};
  

请注意,您不太可能需要对骨骼进行非仿射变换,因此您应该使用XMFLOAT4X3来节省内存,更重要的是传输带宽

例如,在DirectX Tool Kit中,SkinnedEffect着色器的最大骨骼数为72.它使用的CB如下所示:

struct SkinnedEffectConstants
{
    XMVECTOR diffuseColor;
    XMVECTOR emissiveColor;
    XMVECTOR specularColorAndPower;

    XMVECTOR lightDirection[IEffectLights::MaxDirectionalLights];
    XMVECTOR lightDiffuseColor[IEffectLights::MaxDirectionalLights];
    XMVECTOR lightSpecularColor[IEffectLights::MaxDirectionalLights];

    XMVECTOR eyePosition;

    XMVECTOR fogColor;
    XMVECTOR fogVector;

    XMMATRIX world;
    XMVECTOR worldInverseTranspose[3];
    XMMATRIX worldViewProj;

    XMVECTOR bones[SkinnedEffect::MaxBones][3];
};

DGSLEffect蒙皮着色器使用五个不同的CB,其中一个包含骨骼:

// Slot 4
struct BoneConstants
{
    XMVECTOR Bones[DGSLEffect::MaxBones][3];
};
  

最初的VS Starter Kit DGSL蒙皮着色器支持59块骨骼。

你可能会问,为什么72?

这是因为借用XNA Game Studio 4的DirectX Tool Kit中的内置着色器支持Direct3D Feature Level 9.1硬件。在内部,这些着色器使用vs_2_0配置文件,该配置文件需要256个向量常量。 72块骨头占据了其中的216块,剩下的常量将其推高到242,这样就可以为10级实施提供十几个。

如果您需要功能级别10.0或更高版本的硬件,则可以将其扩大而不会对性能产生太大影响。请记住,CB的总大小会影响更新的成本。