1
\$\begingroup\$

I would like to create cloth simulation. Which type of buffer should i use for vertices. I will need to update them on every frame. And how updates need to be done. I'm new to graphics programming, but still i'm mostly interesting in high level overview. If there is open-source project implementing it, reference to it would be of help.

For now i have only rigid body geometries. For this i create a resource with

    THROW_IF_FAILED(g_device->CreateCommittedResource(
        &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
        D3D12_HEAP_FLAG_NONE,
        &CD3DX12_RESOURCE_DESC::Buffer(byteSize),
        D3D12_RESOURCE_STATE_COPY_DEST,
        nullptr,
        IID_PPV_ARGS(buffer_.GetAddressOf())));

Then i update it with initial data using another upload buffer to initialize first buffer. Lastly i transition first buffer into D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER state.


Well, i got some comments directing me toward DirectX11, but for my purposes i will better use DirectX12, and again, i'm pretty matured programmer and just need a highlevel overview of what need to be done.

For example,

create default buffer with geometry, then create upload heap, and when needed create placed resource buffer to upload data into your default buffer.

But here a lot of questions arise. For now i use frame resources e.g. for transforms to update them on each frame and do not stall CPU. But if i will copy once a frame to the same default buffer will my it cause stalling? And should i use different queue for copying, and how then do resource state transitioning?

From what i understood for now, i need to implement this, but how to implement CopyResource functionality?

enter image description here

\$\endgroup\$
8
  • \$\begingroup\$ Slightly off-topic: If you are new to graphics development you should most likely prefer using DX11. DX12 is intended for performance intensive applications (e.g.: games) and requires a lot of manual management from the programmer (while in older API versions those are handled by the OS and drivers). \$\endgroup\$ Mar 28 '17 at 7:04
  • 1
    \$\begingroup\$ @UnholySheep i spent a lot of time to start with DirectX12, and now i have simple rendering system using it, and i would like to continue this way:) \$\endgroup\$
    – Yola
    Mar 28 '17 at 7:07
  • \$\begingroup\$ In that case it's somewhat unclear what you want to do differently for your cloth simulation rendering (e.g.: what should be different from the way you render other objects, what have you tried doing and where are the problems). \$\endgroup\$ Mar 28 '17 at 7:33
  • 1
    \$\begingroup\$ "I pushed a boulder halfway up a mountain instead of a small rock, but since I'm already halfway, I might as well just continue" tis is basically you, but instead of being halfway up, you're only 5% up the mountain. \$\endgroup\$
    – Bálint
    Mar 28 '17 at 8:21
  • \$\begingroup\$ I agree with Sheep and Balint, DX 12 is only needed if you have cpu overhead issues, sure some of the advanced things like async compute and bindles resources can help but. In fact if you use it wrong then your perf will be lower than using DX11. If you are stuck here I would really go have a look at DX11. Why did you pick DX12? \$\endgroup\$ Mar 28 '17 at 23:14
2
\$\begingroup\$

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:

  1. Create a resource in the DEFAULT heap type

  2. Create a resource of the same layout in the UPLOAD heap. You assign it a D3D12_RESOURCE_STATE_COPY_SOURCE initial resource state.

  3. Copy data with the CPU into the UPLOAD resource.

  4. Submit a CopyResource to a command-list to move data from the UPLOAD resource to the DEFAULT resource.

  5. 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: D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, or D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE.

  6. 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.

  7. 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.

  8. 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 GeometricPrimitive, 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 ResourceUploadBatch and GraphicsMemory in the tool kit.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.