This is an old question, so I'm not sure how relevant this answer will be now, but...
In DirectX 11 there are "4 kinds" of resources indicated by their
D3D11_USAGE at creation time.
D3D11_USAGE_IMMUTABLE indicates that the texture/VB/IB was to be immediately filled with data passed as
initData and then would never change again.
This was meant as an optimization, but it was often hard to use in practice. Many apps created a set of textures for streaming-style experiences and reused them, so this wasn't an option. Others had to use auto-gen mips which can't use this flag, etc.
D3D11_USAGE_DEFAULT indicates that the resource should reside in Video RAM and was only accessible by the GPU. On many hardware designs, render targets and depth/stencil buffers must be this usage type, and is usually the 'optimal' choice for resources that will be loaded once or occasionally, but used almost every render frame.
D3D11_USAGE_STAGING indicates the resource is in standard system memory. The GPU can not access this memory directly although the driver may use a DMA engine to read or write this data to GPU-accessible memory. This is normally used to create resources that are copied by Direct3D to the "default" video memory or captured from such memory.
D3D11_USAGE_DYNAMIC indicates that the resource should reside somewhere where both the CPU and the GPU can access it. This resource style is designed for updating 'per-frame' VBs/IBs/ or textures generated by the CPU, but is generally not as fast to access as default memory by the GPU.
Of course all this is abstracted from the real hardware and you can have many different kinds of architectures with different trade-offs. For example, the Xbox consoles are 'Unified Memory Architectures' meaning that the GPU and CPU can access all the same memory, so "DEFAULT", "STAGING", and "DYNAMIC" were all the same thing at least from a high-level.
So with all that out of the way, DirectX 12 expects you to create resources in the "DEFAULT" pool for the same kinds of cases that you'd use
D3D11_USAGE_DEFAULT. The DirectX 12 Runtime doesn't do 'magic behind your back', so there's no implicit uploading system. You have to create a resource in a
UPLOAD heap which is accessible by the CPU and copy data into that resource.
From there you can render directly from the
UPLOAD heap, which is essentially the same as
D3D11_USAGE_DYNAMIC. More often, you set up a copy from the "upload" heap copy a "default" pool resource.
In DirectX 12 you have to manage all the resource state and synchronization as well--think "lockfree" programming. This means for correctness, you need to inject resource barriers into the command-list that indicate state transitions.
Putting it all together for a USAGE_DEFAULT style resource:
Create a resource in the DEFAULT heap type
Create a resource of the same layout in the UPLOAD heap. You assign it a
D3D12_RESOURCE_STATE_COPY_SOURCE initial resource state.
Copy data with the CPU into the UPLOAD resource.
Submit a CopyResource to a command-list to move data from the UPLOAD resource to the DEFAULT resource.
Then add a resource barrier to the command-list which transitions the resource from "COPY_SOURCE" to something you can use to render which depends on the resource usage:
At some point you need to inject a fence into the command-list because you the programmer have to keep the UPLOAD resource alive until the fence is crossed or you will crash the app/GPU.
Then you can submit work to use that resource. Because of the resource barrier, you know at that point the resource will be completely filled out and in the proper state for the GPU to use.
Keep in mind nothing has happened yet until you execute the command-list.
For a USAGE_DYNAMIC style resource, you can just stop with the data in the UPLOAD heap and transition it to the right resource state to render.
See Microsoft Docs
This process is what the
ResourceUploadBatch class in DirectX Tool Kit for DX12 helps manage. Constant Buffers use a similar model, but are typically fenced 'per-frame' and kept alive for 2 or 3 frames depending on the swapchain. That's what the
GraphicsMemory class manages.
The DirectX Tool Kit leverages the 'simple' nature of the "upload' heap for
Model, etc. where you can just create the VB/IB/etc. on the fly and render directly from there. For better performance, you use the
ResourceUploadBatch with a LoadStaticBuffers method which moves the data from "upload" to "default".
For cases where you just want to get some data from system memory into GPU memory like your situation, the BufferHelpers functions submit the right kind of object using
GraphicsMemory in the tool kit.