当前位置: 首页 > news >正文

MiniEngine学习笔记 : CommandListManager

学习CommandListManager类

  • 前言
  • CommandQueue
    • (1) 源码展示
    • (2) 源码分析
    • (3) 类使用分析
    • (4) 类改进

前言

  • 书接上回CommandQueue,本篇文章分析CommandListManager。

CommandQueue

(1) 源码展示

  • 类头文件如下:
#pragma once#include "CommandQueue.h"class CommandListManager
{friend class CommandContext;public:CommandListManager();~CommandListManager();void Create(ID3D12Device* pDevice);void Shutdown();CommandQueue& GetGraphicsQueue(void) { return m_GraphicsQueue; }CommandQueue& GetComputeQueue(void) { return m_ComputeQueue; }CommandQueue& GetCopyQueue(void) { return m_CopyQueue; }CommandQueue& GetQueue(D3D12_COMMAND_LIST_TYPE Type = D3D12_COMMAND_LIST_TYPE_DIRECT){switch (Type){case D3D12_COMMAND_LIST_TYPE_COMPUTE: return m_ComputeQueue;case D3D12_COMMAND_LIST_TYPE_COPY: return m_CopyQueue;default: return m_GraphicsQueue;}}ID3D12CommandQueue* GetCommandQueue(){return m_GraphicsQueue.GetCommandQueue();}void CreateNewCommandList(D3D12_COMMAND_LIST_TYPE Type,ID3D12GraphicsCommandList** List,ID3D12CommandAllocator** Allocator);// Test to see if a fence has already been reachedbool IsFenceComplete(uint64_t FenceValue){return GetQueue(D3D12_COMMAND_LIST_TYPE(FenceValue >> 56)).IsFenceComplete(FenceValue);}// The CPU will wait for a fence to reach a specified valuevoid WaitForFence(uint64_t FenceValue);// The CPU will wait for all command queues to empty (so that the GPU is idle)void IdleGPU(void){m_GraphicsQueue.WaitForIdle();m_ComputeQueue.WaitForIdle();m_CopyQueue.WaitForIdle();}private:ID3D12Device* m_Device;CommandQueue m_GraphicsQueue;CommandQueue m_ComputeQueue;CommandQueue m_CopyQueue;
};
  • 类源文件如下:
#include "pch.h"
#include "CommandListManager.h"CommandListManager::CommandListManager() :m_Device(nullptr),m_GraphicsQueue(D3D12_COMMAND_LIST_TYPE_DIRECT),m_ComputeQueue(D3D12_COMMAND_LIST_TYPE_COMPUTE),m_CopyQueue(D3D12_COMMAND_LIST_TYPE_COPY)
{
}CommandListManager::~CommandListManager()
{Shutdown();
}void CommandListManager::Shutdown()
{m_GraphicsQueue.Shutdown();m_ComputeQueue.Shutdown();m_CopyQueue.Shutdown();
}void CommandListManager::Create(ID3D12Device* pDevice)
{ASSERT(pDevice != nullptr);m_Device = pDevice;m_GraphicsQueue.Create(pDevice);m_ComputeQueue.Create(pDevice);m_CopyQueue.Create(pDevice);
}void CommandListManager::CreateNewCommandList(D3D12_COMMAND_LIST_TYPE Type, ID3D12GraphicsCommandList** List, ID3D12CommandAllocator** Allocator)
{ASSERT(Type != D3D12_COMMAND_LIST_TYPE_BUNDLE, "Bundles are not yet supported");switch (Type){case D3D12_COMMAND_LIST_TYPE_DIRECT: *Allocator = m_GraphicsQueue.RequestAllocator(); break;case D3D12_COMMAND_LIST_TYPE_BUNDLE: break;case D3D12_COMMAND_LIST_TYPE_COMPUTE: *Allocator = m_ComputeQueue.RequestAllocator(); break;case D3D12_COMMAND_LIST_TYPE_COPY: *Allocator = m_CopyQueue.RequestAllocator(); break;}ASSERT_SUCCEEDED(m_Device->CreateCommandList(1, Type, *Allocator, nullptr, MY_IID_PPV_ARGS(List)));(*List)->SetName(L"CommandList");
}void CommandListManager::WaitForFence(uint64_t FenceValue)
{CommandQueue& Producer = Graphics::g_CommandManager.GetQueue((D3D12_COMMAND_LIST_TYPE)(FenceValue >> 56));Producer.WaitForFence(FenceValue);
}

(2) 源码分析

类成员变量如下:

// 设备对象
ID3D12Device* m_Device;// 图形、计算、拷贝命令队列
CommandQueue m_GraphicsQueue;
CommandQueue m_ComputeQueue;
CommandQueue m_CopyQueue;

类方法如下:

// 构造函数,分别构造m_GraphicsQueue、m_ComputeQueue、m_CopyQueue
CommandListManager::CommandListManager() :m_Device(nullptr),m_GraphicsQueue(D3D12_COMMAND_LIST_TYPE_DIRECT),m_ComputeQueue(D3D12_COMMAND_LIST_TYPE_COMPUTE),m_CopyQueue(D3D12_COMMAND_LIST_TYPE_COPY)
{
}// 析构时关闭
CommandListManager::~CommandListManager()
{Shutdown();
}// 关闭,依次调用每个CommandQueue关闭
void CommandListManager::Shutdown()
{m_GraphicsQueue.Shutdown();m_ComputeQueue.Shutdown();m_CopyQueue.Shutdown();
}// 创建,依次创建每个CommandQueue
void CommandListManager::Create(ID3D12Device* pDevice)
{ASSERT(pDevice != nullptr);m_Device = pDevice;m_GraphicsQueue.Create(pDevice);m_ComputeQueue.Create(pDevice);m_CopyQueue.Create(pDevice);
}// 创建新的命令列表,传入命令类型,
// 剩余两个参数返回创建的命令列表和分配器。
void CommandListManager::CreateNewCommandList(D3D12_COMMAND_LIST_TYPE Type, ID3D12GraphicsCommandList** List, ID3D12CommandAllocator** Allocator)
{// 不支持D3D12_COMMAND_LIST_TYPE_BUNDLEASSERT(Type != D3D12_COMMAND_LIST_TYPE_BUNDLE, "Bundles are not yet supported");// 根据类型,选择对应CommandQueue申请命令分配器switch (Type){case D3D12_COMMAND_LIST_TYPE_DIRECT: *Allocator = m_GraphicsQueue.RequestAllocator(); break;case D3D12_COMMAND_LIST_TYPE_BUNDLE: break;case D3D12_COMMAND_LIST_TYPE_COMPUTE: *Allocator = m_ComputeQueue.RequestAllocator(); break;case D3D12_COMMAND_LIST_TYPE_COPY: *Allocator = m_CopyQueue.RequestAllocator(); break;}// 创建命令列表,返回到List中ASSERT_SUCCEEDED(m_Device->CreateCommandList(1, Type, *Allocator, nullptr, MY_IID_PPV_ARGS(List)));(*List)->SetName(L"CommandList");
}// 等待围栏完成
void CommandListManager::WaitForFence(uint64_t FenceValue)
{/** 这里通过全局CommandListManager变量-Graphics::g_CommandManager,* 调用GetQueue获取围栏对应的CommandQueue,然后调用CommandQueue::WaitForFence,* 我也不太理解明明此类就是CommandListManager,为什么还要定位到全局CommandListManager变量里去?* 总之这样不利于独立组件CommandListManager,我将改为使用此对象直接调用GetQueue。*/CommandQueue& Producer = Graphics::g_CommandManager.GetQueue((D3D12_COMMAND_LIST_TYPE)(FenceValue >> 56));Producer.WaitForFence(FenceValue);
}// 获取CommandQueue
CommandQueue& CommandListManager::GetGraphicsQueue(void) { return m_GraphicsQueue; }
CommandQueue& CommandListManager::GetComputeQueue(void) { return m_ComputeQueue; }
CommandQueue& CommandListManager::GetCopyQueue(void) { return m_CopyQueue; }// 获取某类型CommandQueue
CommandQueue& CommandListManager::GetQueue(D3D12_COMMAND_LIST_TYPE Type = D3D12_COMMAND_LIST_TYPE_DIRECT)
{switch (Type){case D3D12_COMMAND_LIST_TYPE_COMPUTE: return m_ComputeQueue;case D3D12_COMMAND_LIST_TYPE_COPY: return m_CopyQueue;default: return m_GraphicsQueue;}
}// 获取图形CommandQueue
ID3D12CommandQueue* CommandListManager::GetCommandQueue()
{return m_GraphicsQueue.GetCommandQueue();
}// 测试是否已到达围栏
bool CommandListManager::IsFenceComplete(uint64_t FenceValue)
{return GetQueue(D3D12_COMMAND_LIST_TYPE(FenceValue >> 56)).IsFenceComplete(FenceValue);
}// CPU 将等待所有命令队列清空(以便 GPU 空闲)
void CommandListManager::IdleGPU(void)
{m_GraphicsQueue.WaitForIdle();m_ComputeQueue.WaitForIdle();m_CopyQueue.WaitForIdle();
}

(3) 类使用分析

  • 可以看到CommandListManager包含了图形、计算、拷贝CommandQueue,提供CreateNewCommandList可创建命令列表,可获取每个CommandQueue。

(4) 类改进

  • WaitForFence方法依赖于全局变量实现,妨碍作为独立组件,主要就是修改此方法,改为使用自身查找CommandQueue实现。
  • 改进后CommandListManager类代码位于:CommandListManager,可作为独立组件使用。
http://www.dtcms.com/a/568507.html

相关文章:

  • 人工智能讲师数据治理讲师叶梓《数字化转型与大模型技术应用培训提纲》
  • 1.7.课设实验-数据结构-二叉树-文件夹创建系统
  • 互联网大学生创新创业项目计划书seo网址查询
  • 同时打开两个浏览器页面,关闭 A 页面的时候,要求 B 页面同时关闭,怎么实现?
  • 什么是react?
  • Arbess零基础学习 - 使用Arbess+GitLab实现 React.js 项目自动化构建/主机部署
  • 从事网站开发需要的证书网页设计免费网站推荐
  • 任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存【示例】
  • 【开题答辩实录分享】以《基于java的宿舍楼洗衣机预约管理系统》为例进行答辩实录分享
  • 如何在iPhone 17/16/15上显示电池百分比
  • 网站换主机引擎网站推广法
  • 【普中STM32F1xx开发攻略--标准库版】-- 第 13 章 STM32 位带操作
  • MySQL绿色版完整教程:下载、安装、配置与远程访问
  • 集合(开发重点)
  • 如何通过第三方API接口获取拼多多店铺信息?
  • ⸢ 拾贰 ⸥⤳ 实战攻防演练:红蓝对抗 有效性检验
  • Flutter 与 Native的比较
  • 做网站要用到什么泰安有哪些景点
  • Java EE - Thread类的基本使用
  • 社会真相社会现实丛林社会强者思维社会关系价值交换社会法则社会圈子社会阶层电子书籍PDF
  • 轻量化的网络模型:SqueezeNet 详解与复现(已解决)
  • Adobe Acrobat DC PDF如何批量文本替换
  • 帝国cms 微信小程序获取手机号码的api接口
  • 南昌网站搭建服务免费涨1000粉丝网站
  • linux USB摄像头不停掉线问题
  • 本地开发调试企业微信回调接口不顺畅?利用 CPolar 实现内网穿透,快速建立公网访问通道
  • 金融数仓项目介绍
  • 《投资-154》Beta(贝塔系数)是金融领域中用于衡量资产(如股票、基金、投资组合)系统性风险的核心指标,它反映了资产相对于市场整体波动的敏感程度。
  • 【开发技能】借助Aspose.Words,用C#开发一个Markdown到 Word的转换器
  • React 中 useCallback 的基本使用和原理解析