Jump to content
  • Advertisement

fighting_falcon93

Member
  • Content Count

    12
  • Joined

  • Last visited

Community Reputation

1 Neutral

About fighting_falcon93

  • Rank
    Member

Personal Information

  • Interests
    Art
    Audio
    Business
    Design
    Education
    Programming

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. fighting_falcon93

    DX12 Management of CommandQueue/CommandAllocator/CommandList

    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?
  2. fighting_falcon93

    DX12 Management of CommandQueue/CommandAllocator/CommandList

    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?
  3. fighting_falcon93

    DX12 Management of CommandQueue/CommandAllocator/CommandList

    No, memory is not a problem, but if I'm going to release it 1-2 frames later, that means that I need to store the pointers to the upload buffers somewhere, and on top of that, each frame I'd need to check if there's something to remove, which feels like a waste of performance when the there's only cleanup to do after initialization. Basically I'd check an empty list every time I call the update function of of subsystem. Unless there's some better way of cleaning it up?
  4. fighting_falcon93

    DX12 Management of CommandQueue/CommandAllocator/CommandList

    I'm thinking mostly of upload buffers. In that case, the subsystem needs to know when it's safe to release the upload buffer.
  5. fighting_falcon93

    DX12 Management of CommandQueue/CommandAllocator/CommandList

    Thank you very much for your reply @pcmaster. I'm not sure that I understand what you mean in the first part. If I understand you correctly, do you mean that I should do something like this: void System::Render() { index = swapChain->GetCurrentBackBufferIndex; WaitForPreviousFrame(); commandAllocators[index][0]->Reset(); commandAllocators[index][1]->Reset(); commandAllocators[index][2]->Reset(); commandLists[0]->Reset(commandAllocators[index][0], ...); commandLists[1]->Reset(commandAllocators[index][1], ...); commandLists[2]->Reset(commandAllocators[index][2], ...); SubSystem1::Render(commandLists[0]); SubSystem2::Render(commandLists[1]); SubSystem3::Render(commandLists[2]); commandLists[0]->Close(); commandLists[1]->Close(); commandLists[2]->Close(); commandQueue->ExecuteCommandLists(3, commandLists); swapChain->Present(...); Signal(...); } void SubSystem1::Render(ID3D12GraphicsCommandList* commandList) { commandList->[...]; commandList->[...]; commandList->[...]; } void SubSystem2::Render(ID3D12GraphicsCommandList* commandList) { commandList->[...]; commandList->[...]; commandList->[...]; } void SubSystem3::Render(ID3D12GraphicsCommandList* commandList) { commandList->[...]; commandList->[...]; commandList->[...]; } What I'm thinking about this solution is that there will be problems if a subsystem would like to split up the recording of commands on multiple threads, as that would require more than one command list. Another problem I'm thinking of is if a subsystem would like to execute some commands before proceeding with the rest of the commands. I'm also thinking about the initialization, because there I would need to use a different approach, since during initialization one subsystem might want to execute a command list, wait until it's done, and then record again, for example: void SubSystem1::Initialize() { CreateResource(...); CreateUploadBuffer(...); ExecuteCopyCommand(...); WaitForGPU(...); ReleaseUploadBuffer(...); DoSomethingWithResource(...); } I understand the part about command allocators and threads though, and I will make sure that each thread has their own command list and pair of command allocators so that they don't have to compete for the mutex.
  6. fighting_falcon93

    DX12 Management of CommandQueue/CommandAllocator/CommandList

    Thank you very much for your reply @MJP. I understand, will change this directly, thank you for letting me know. Multiple command lists can use the same command allocator. Is that a good idea and how would this work with threading? Also, what is considered better practice, to update multiple subsystems in parallel on their own thread, or, to update the subsystems sequentially but using multiple threads to split up the internal work? The main problem is that I can't make up my mind when it comes to the design. I like the approach of giving each subsystem their own command list and command allocators, but it bothers me that then each subsystem needs to check whether the GPU is done with the allocator or not. If I would do it like you suggested with a RenderBegin() and RenderEnd(), then I wouldn't need to check this, but at the same time, I would be limited to only calling execute once per subsystem per frame, right? Could this limitation lead to problems later? I'm creating resources (constant buffers, textures, etc) and then uploading data through upload buffers. The main issue I'm having is that I can't release the upload buffers until the GPU is done with the copying, and in order to do that, I need to execute the command list, wait until the GPU has finished with it, and only then can I release it. From what I've understood, I cannot record commands that tell the GPU to release resources itself, right? So this issue I'm having with command lists is quite related to the management of upload buffers, which I struggle with aswell. I'll check this out, thank you for the advice.
  7. Hello! I need some guidance on CommandQueue/CommandAllocator/CommandList management. In my current project I have a few "systems" that need to execute graphical commands, such as rendering terrain, rendering water, rendering particles etc. Right now my project is very simple so I'm not even using command lists during initialization. However, that's starting to be required. Currently I'm just using a single command queue with a ring buffer of 2 command allocators that get recorded by a single command list. Each time I render the scene, a command allocator and a command list is being reset and then recorded. After all commands has been recorded, the list is executed and the swap chain is flipped. Here's some pseudo-code: void Initialize() { [...] device->CreateCommandQueue(...); device->CreateCommandAllocator(...); // commandAllocator[0] device->CreateCommandAllocator(...); // commandAllocator[1] device->CreateCommandList(...); commandList->Close(); [...] } void Render() { WaitForPreviousFrame(); commandAllocator[i]->Reset(); // i = swapChain->GetCurrentBackBufferIndex() commandList->Reset(...); RecordAllCommands(); commandList->Close(); commandQueue->ExecuteCommandLists(...); Signal(...); swapChain->Present(...); } The issue with this is that I cannot record commands during initialization, and with this design it's also quite cumbersome to execute command lists multiple times during one frame since the command allocator ring buffer is tied together with the swap chain buffer index. So I started to think about how I should redesign this, preferably also with future support for threading. And I've thought about it for quite some time now and can't come up with a good solution. One idea is that each system should have their own command list with a ring buffer of 2 command allocators, and then record it and just use a global command queue to execute the list. This works well from a parallel point of view, but the issue is that now each system need to check individually if the GPU is done with the commands before resetting the command allocator. This feels like a huge CPU waste. Another idea is that there is only one global command list, that is aviable already during initialization of other systems, and after the initialization this command list gets executed, before entering the game loop. During the game loop, the global command list gets executed once per frame as I do it now. However, there are 2 issues with this. First of all, some systems might want to execute their commands earlier than at the end of each frame. Secondly, if multiple threads record into the same command list, then we might get a situation like this: commandList->SetPipelineState(pipelineState1); // Thread 1 wants pipelineState1. commandList->SetPipelineState(pipelineState2); // Thread 2 wants pipelineState2. [...] commandList->DrawInstanced(...); // Thread 1 expects pipelineState1 to be set... I'm out of ideas of how to implement this in a simple and elegant way. Or maybe I'm doing this entirely wrong. Basically what I need is: Systems should be able to record commands already during initialization. Atleast during initialization, it should be possible to execute commands in multiple steps and even wait for the GPU to complete them. When rendering the scene, it would be nice if multiple threads could record commands in parallel. Does any of you have a good solution to this problem? What is the AAA game engine way of dealing with this?
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!