<p><code>UpdateSubresources</code> is a helper function. Inside it is another <code>memcpy</code>. I would recommend simply rewriting it - source is in <a href="https://code.msdn.microsoft.com/Direct3D-12-UAP-Sample-ecb1779f/sourcecode?fileId=139518&amp;pathId=1775568253" rel="nofollow noreferrer">d3dx12.h</a>. Then you will be able to copy your data no more than necessary.</p>

CC BY-SA 4.0
2018-05-11T19:14:43.657Z
Hmm, yeah... the helper function essentially amounts to the following in my case:

```commandList->CopyBufferRegion(meshPart.m_mainBuffer.Get(), 0, meshPart.m_uploadBuffer.Get(), 0, totalBufferSize);```


I'll keep my Map+memcpy and just call CopyBufferRegion myself without going through the helper. Thanks for the reality check.
deadpin
CC BY-SA 4.0
2018-05-11T10:23:54.413Z
2018-05-11T10:53:26.590Z
2018-05-11T10:53:26.590Z
Derag
<p>Consider a situation where there are 3 different buffers describing a particular mesh piece: <code>vBuffer</code>, <code>nBuffer</code>, <code>iBuffer</code> (vertices, normals, and indices) which equate to <code>totalBufferSize</code> in aggregate.</p>

<p>I want to save these 3 buffers to the same default heap (D3D12_HEAP_TYPE_DEFAULT).  I know I still need to use an upload heap (D3D12_HEAP_TYPE_UPLOAD) as an intermediary but I can't figure out how to eliminate extra copies.</p>

<p>Currently my code (which works) does the following:</p>

<pre><code>    const D3D12_HEAP_PROPERTIES defaultHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
    const D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);

...

    const CD3DX12_RESOURCE_DESC resourceDescV = CD3DX12_RESOURCE_DESC::Buffer(totalBufferSize);
    DX::ThrowIfFailed(device-&gt;CreateCommittedResource(
        &amp;defaultHeapProperties,
        D3D12_HEAP_FLAG_NONE,
        &amp;resourceDescV,
        D3D12_RESOURCE_STATE_COPY_DEST,
        nullptr,
        IID_PPV_ARGS(meshPart.m_mainBuffer.ReleaseAndGetAddressOf())));

    DX::ThrowIfFailed(device-&gt;CreateCommittedResource(
        &amp;uploadHeapProperties,
        D3D12_HEAP_FLAG_NONE,
        &amp;resourceDescV,
        D3D12_RESOURCE_STATE_GENERIC_READ,
        nullptr,
        IID_PPV_ARGS(meshPart.m_uploadBuffer.ReleaseAndGetAddressOf())));

    uint8_t * bufferStart{};
    const CD3DX12_RANGE readRange(0, 0);
    DX::ThrowIfFailed(meshPart.m_uploadBuffer-&gt;Map(0, &amp;readRange, reinterpret_cast&lt;void **&gt;(&amp;bufferStart)));

    // Can these be eliminated?
    uint32_t offset{};
    std::memcpy(bufferStart, vBuffer.data, vBuffer.totalSize);
    offset += vBuffer.totalSize;
    std::memcpy(bufferStart + offset, nBuffer.data, nBuffer.totalSize);
    offset += nBuffer.totalSize;
    std::memcpy(bufferStart + offset, iBuffer.data, iBuffer.totalSize);

    D3D12_SUBRESOURCE_DATA bufferData{};
    bufferData.pData = bufferStart;
    bufferData.RowPitch = totalBufferSize;
    bufferData.SlicePitch = totalBufferSize;

    UpdateSubresources&lt;1&gt;(commandList, meshPart.m_mainBuffer.Get(), meshPart.m_uploadBuffer.Get(), 0, 0, 1, &amp;bufferData);
    CD3DX12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(meshPart.m_mainBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
    commandList-&gt;ResourceBarrier(1, &amp;barrier);
</code></pre>

<p>However, I'm trying to figure out if I can eliminate those std::memcpy calls.   All examples of UpdateSubresources I've seen do not explicitly Map+memcpy into the upload buffer.  They just set <code>D3D12_SUBRESOURCE_DATA.pData</code> directly.</p>

<p>I tried calling using <code>UpdateSubresources&lt;3&gt;</code> and passing in an array of D3D12_SUBRESOURCE_DATA, each pointing to the beginning of my mesh buffers, but the validation layer didn't like that and threw an exception.</p>

<p>Is it possible to upload all 3 buffers in one step here -- without the explicit Map and memcpy steps?</p>

<directx12>
DirectX 12: Uploading multiple buffers to 1 default heap using the UpdateSubresources API without explicit copies
deadpin
# DirectX 12: Uploading multiple buffers to 1 default heap using the UpdateSubresources API without explicit copies

(Asked by: username_0 on 2018-05-11)

Consider a situation where there are 3 different buffers describing a particular mesh piece: `vBuffer`, `nBuffer`, `iBuffer` (vertices, normals, and indices) which equate to `totalBufferSize` in aggregate.

I want to save these 3 buffers to the same default heap (D3D12\_HEAP\_TYPE\_DEFAULT). I know I still need to use an upload heap (D3D12\_HEAP\_TYPE\_UPLOAD) as an intermediary but I can't figure out how to eliminate extra copies.

Currently my code (which works) does the following:

```
    const D3D12_HEAP_PROPERTIES defaultHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
    const D3D12_HEAP_PROPERTIES uploadHeapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD);

...

    const CD3DX12_RESOURCE_DESC resourceDescV = CD3DX12_RESOURCE_DESC::Buffer(totalBufferSize);
    DX::ThrowIfFailed(device->CreateCommittedResource(
        &defaultHeapProperties,
        D3D12_HEAP_FLAG_NONE,
        &resourceDescV,
        D3D12_RESOURCE_STATE_COPY_DEST,
        nullptr,
        IID_PPV_ARGS(meshPart.m_mainBuffer.ReleaseAndGetAddressOf())));

    DX::ThrowIfFailed(device->CreateCommittedResource(
        &uploadHeapProperties,
        D3D12_HEAP_FLAG_NONE,
        &resourceDescV,
        D3D12_RESOURCE_STATE_GENERIC_READ,
        nullptr,
        IID_PPV_ARGS(meshPart.m_uploadBuffer.ReleaseAndGetAddressOf())));

    uint8_t * bufferStart{};
    const CD3DX12_RANGE readRange(0, 0);
    DX::ThrowIfFailed(meshPart.m_uploadBuffer->Map(0, &readRange, reinterpret_cast<void **>(&bufferStart)));

    // Can these be eliminated?
    uint32_t offset{};
    std::memcpy(bufferStart, vBuffer.data, vBuffer.totalSize);
    offset += vBuffer.totalSize;
    std::memcpy(bufferStart + offset, nBuffer.data, nBuffer.totalSize);
    offset += nBuffer.totalSize;
    std::memcpy(bufferStart + offset, iBuffer.data, iBuffer.totalSize);

    D3D12_SUBRESOURCE_DATA bufferData{};
    bufferData.pData = bufferStart;
    bufferData.RowPitch = totalBufferSize;
    bufferData.SlicePitch = totalBufferSize;

    UpdateSubresources<1>(commandList, meshPart.m_mainBuffer.Get(), meshPart.m_uploadBuffer.Get(), 0, 0, 1, &bufferData);
    CD3DX12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(meshPart.m_mainBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
    commandList->ResourceBarrier(1, &barrier);

```

However, I'm trying to figure out if I can eliminate those std::memcpy calls. All examples of UpdateSubresources I've seen do not explicitly Map+memcpy into the upload buffer. They just set `D3D12_SUBRESOURCE_DATA.pData` directly.

I tried calling using `UpdateSubresources<3>` and passing in an array of D3D12\_SUBRESOURCE\_DATA, each pointing to the beginning of my mesh buffers, but the validation layer didn't like that and threw an exception.

Is it possible to upload all 3 buffers in one step here -- without the explicit Map and memcpy steps?

**Tags:** directx12


---

## 1 answers

### Answer by username_1 on 2018-05-11. Score: 0 | Accepted answer

`UpdateSubresources` is a helper function. Inside it is another `memcpy`. I would recommend simply rewriting it - source is in [d3dx12.h](https://code.msdn.microsoft.com/Direct3D-12-UAP-Sample-ecb1779f/sourcecode?fileId=139518&pathId=1775568253). Then you will be able to copy your data no more than necessary.

> **Comments:**
> **username_0**: Hmm, yeah... the helper function essentially amounts to the following in my case:  ```commandList->CopyBufferRegion(meshPart.m_mainBuffer.Get(), 0, meshPart.m_uploadBuffer.Get(), 0, totalBufferSize);```   I'll keep my Map+memcpy and just call CopyBufferRegion myself without going through the helper. Thanks for the reality check.  

---

