MiniEngine中的命令队列、命令列表、命令分配器

命令队列

类名: CommandQueue
GPU会不断的执行命令队列中的指令,根据d3dx12.h能够看到一个GPU维护多种类型的命令队列ui

命令分配器

类名:CommandAllocatorPool
记录命令列表插入的GPU指令this

命令列表

类名:CommandListManager
插入GPU指令到命令分配器中3d

围栏

能够理解为特殊的GPU指令,GPU执行到围栏指令时,会更新围栏的值,用于判断GPU执行到了哪一步code

基本流程:

  1. 建立命令队列、围栏
  2. 建立命令列表、命令分配器
  3. 命令列表插入须要执行的指令
  4. 命令列表插入围栏值
  5. 调用ExecuteCommandLists,使GPU开始执行命令列表中记录的指令。
  6. 此时命令列表已经能够重置了,可是命令分配器不能够重置,由于不知道GPU是否是执行完毕了
  7. 命令分配器的重置,能够选择死等围栏值更新,或者新建一个命令分配器开始下一轮的指令插入

MiniEngine:

1. CommandAllocatorPool

命令分配器池子。用于管理生成并复用命令分配器。队列

2. CommandQueue

命令队列。根据类型维护一个命令分配器池子、独立赋值的围栏string

3. CommandListManager

维护命令队列。it

MiniEngine基本渲染流程:

1.初始化 CommandListManager::Create

直接生成了3个命令队列。命令队列内部有本身的分配器池子、围栏。
这个会在程序启动时初始化。io

2.开启一个绘制 CommandContext::Begin

CommandContext& CommandContext::Begin( const std::wstring ID )
{
    CommandContext* NewContext = g_ContextManager.AllocateContext(D3D12_COMMAND_LIST_TYPE_DIRECT);
    NewContext->SetID(ID);
    if (ID.length() > 0)
        EngineProfiling::BeginBlock(ID, NewContext);
    return *NewContext;
}

AllocateContext中初始化或重置一个命令列表 CommandListManager::CreateNewCommandListclass

3.结束一个绘制 CommandContext::Finish

uint64_t CommandContext::Finish( bool WaitForCompletion )
{
    ...

    CommandQueue& Queue = g_CommandManager.GetQueue(m_Type);

    // 返回本次命令队列的围栏值
    uint64_t FenceValue = Queue.ExecuteCommandList(m_CommandList);
    // 这里面会把命令分配器与围栏值关联起来,存到等待队列中
    // 等下次再想分配一个命令分配器时,会根据已经执行完的围栏值,来判断等待队列中的分配器是否能够复用
    Queue.DiscardAllocator(FenceValue, m_CurrentAllocator);
    m_CurrentAllocator = nullptr;

    ...

    if (WaitForCompletion)
        g_CommandManager.WaitForFence(FenceValue);

    g_ContextManager.FreeContext(this);

    return FenceValue;
}
相关文章
相关标签/搜索