-3

I'm trying to copy vector of DirectX::XMMATRIX elements into a Direct3D vertex shader constant buffer, but it only copies the first element (which is 4x4 float matrix, which is 64 bytes), resulting in an exception (it expects 3 elements, 192 bytes total, which vector has)

Here's a sample code:

template<typename C>
void Update(const std::vector<C>* cbuf)
{
    D3D11_MAPPED_SUBRESOURCE msr = {};
    GetContext()->Map(m_pConstBuffer.Get(), 0u, D3D11_MAP_WRITE_DISCARD, 0u, &msr);
    memcpy(msr.pData, &cbuf[0], sizeof(C) * cbuf->size());
    GetContext()->Unmap(m_pConstBuffer.Get(), 0u);
}

I also tried memcpy(msr.pData, cbuf->data(), sizeof(C) * cbuf->size()), as well as specifically stating to copy 192 bytes - and yes - sizeof(C) * cbuf->size() results in 192 - but it still copies 64 bytes of the first element

So what's wrong? Isn't the vector contiguous?

krz
  • 11
  • 3

1 Answers1

2

The problem here I believe is that you are passing the std::vector as a pointer so &cbuf[0] isn't doing what you think it is doing.

You can also make it a little more generic:

template<typename T>
void Update(T const& cbuf)
{
    auto context = GetContext();
    auto cb = m_pConstBuffer.Get();
    D3D11_MAPPED_SUBRESOURCE msr = {};
    if (SUCCEEDED(context->Map(cb, 0u, D3D11_MAP_WRITE_DISCARD, 0u, &msr)))
    {
        memcpy(msr.pData,
            cbuf.data(),
            sizeof(typename T::value_type) * cbuf.size());
        context->Unmap(cb, 0u);
    }
}

You don't show the creation of the resource so if this doesn't work, try looking at that.

You may want to take a look at DirectX Tool Kit for DX11. There's a MapGuard class similar to what you are doing and the BufferHelpers.h header might give you some ideas as well.

Chuck Walbourn
  • 38,259
  • 2
  • 58
  • 81