Advertisement

Management of CommandQueue/CommandAllocator/CommandList

Started by October 08, 2019 10:51 AM
16 comments, last by MJP 5 years, 4 months ago

Maybe I'm combining too many things, if still unclear, we can break it down a bit.

I understand about the cleanup pool. I just think it's a bit uneccessary to do it that way when I only have cleanup to do directly after initialization has completed, for the rest of all frames there are no cleanup to do at all ?

I'll take into consideration what has been written here and start making some changes in my code to see if any problems show up. One question that already popped up, consider this example:


void System::ExecuteCommands(ID3D12CommandList* commandList)
{
  commandQueue->ExecuteCommandLists(1, &commandList);
}

[Thread1]
{
  [...]
  System::ExecuteCommands(commandList);
  [...]
}

[Thread2]
{
  [...]
  System::ExecuteCommands(commandList);
  [...]
}

Can multiple threads use the same command queue simultaneously? And is it a good idea to do it like this?

Advertisement

Interestingly enough, I haven't found any proof that ID3D12CommandQueue be thread-safe, so I wouldn't count on it (links, anyone?). Put a mutex around it and you're safe - you won't submit that many command lists during a frame for this to block you (that goes for everything I wrote -- if it's only a few dozen a frame, fǜck it and use a mutex; if it's thousands, go lock-less). Optimise only after measuring. Don't optimise where you can't gain almost anything. Also it makes sense only if you don't care about their order. If they depend one on another and form a directed tree graph, you'll have to order them yourself, but you're surely aware.

I didn't know you wouldn't call your Initialize every frame. If it's only at the app start, cool :)

I've searched a bit and found this:

https://docs.microsoft.com/en-us/windows/win32/direct3d12/executing-and-synchronizing-command-lists#executing-command-lists

"Applications can submit command lists to any command queue from multiple threads. The runtime will perform the work of serializing these requests in the order of submission."

Do I read it correctly that I can use a single command queue and have multiple threads call its ExecuteCommandList method simultaneously?

Looks like that.

Yes, command queues are thread-safe.

Advertisement

It's probably worth your while to have some sort of "deferred cleanup" mechanism you can use to destroy things that the GPU might still be using. I've handled this in the past by having per-frame lists that the resource can go into when it's no longer needed, and then I'll clean them all up after the waiting for the frame fence.

For uploading resources in particular, the way I handled it was to allocate from a large ring buffer instead of creating/destroying temporary uploading resources. This gives you bounded memory usage, and frees you from having to worry about the cleanup. It also gives you viable a path for doing on-the-fly uploads that happen every frame, without having to go through an expensive memory allocations. I've done things for things like large structured buffers containing parameters for every active light in the world, since you can potentially get improved GPU performance when reading from DEFAULT resources instead of UPLOAD resources. You can look at the implementation that I use for my samples here.

This topic is closed to new replies.

Advertisement