ID3D11Device::CreateBuffer在引擎盖下做什么?

What does ID3D11Device::CreateBuffer do under the hood?

本文关键字:什么 引擎 CreateBuffer ID3D11Device      更新时间:2023-10-16

我知道这个函数会创建一个">缓冲区"。但究竟什么是缓冲区?它是内存中的COM 对象吗?如果是,那么在我的理解中,此函数会接收描述符和一些初始数据以在内存中创建此COM对象,然后将输入ID3D11Buffer**指向的ID3D11Buffer指针设置为新创建的COM对象中的接口。创建 COM 对象后,不再需要初始化数据,我们可以删除它们。一旦我们调用 ID3DBuffer::Release((,下划线 COM 对象将被销毁。我的理解正确吗?

CreateBuffer 返回一个 COM 接口对象ID3D11Buffer*。只要它具有非零引用计数(它从 1 开始;每次调用AddRef加 1,每次调用Release减去 1(,那么它控制的任何资源都是活动的。

至于资源究竟在哪里分配,这真的取决于。你可能会发现本文很有趣,因为它涵盖了 Direct3D 分配资源的不同方式。

更新:您还应该阅读此Microsoft文档对 DirectX 使用的 COM 子集的介绍。

在一般情况下,缓冲区是一个连续的、受管理的内存区域。

内存是一大组可读/写元素的地址(当然,每个地址一个元素(,例如 230个 8 位元素的地址构成 1GiB 内存。

如果只有一个程序并且它静态使用这些地址(例如,从0x1000到0x2000的地址用于存储项目列表(,则不需要管理内存,在这种情况下,缓冲区只是一个连续的地址范围。

但是,如果有多个程序或程序内存使用情况是动态的(例如,这取决于要求从输入中读取多少项(,则必须管理内存。
您必须跟踪哪些范围已在使用中,哪些未在使用中。因此,缓冲区成为具有其属性的连续地址范围(例如,它是否正在使用中(。
缓冲区的属性在不同的内存分配器之间可能会有很大差异,一般来说,我们说缓冲区是托管的,因为我们让内存分配器处理它:找到一个合适的自由范围,标记它已使用,告诉它是否可以向后移动缓冲区,在完成时将其标记为空闲。

对于

共享的每个内存都是如此,因此对于主内存(RAM(和图形内存也是如此。
这是显卡内部的内存,就像主内存一样访问(从 CPU 的角度来看(。

CreateBuffer返回的是主内存中的一个 COM 对象,其中包含处理刚刚分配的缓冲区所需的元数据。
它不包含缓冲区本身,因为此 COM 对象始终在内存中,而缓冲区通常不在内存中(它在图形内存中(。

CreateBuffer要求图形驱动程序在询问的内存中找到合适范围的可用地址,并填写一些元数据
在 CPU 可以访问主内存之前,必须设置一些元数据表(页表(作为其保护机制的一部分。
如果 CPU 需要访问图形内存(可能需要一些额外的步骤,以便在必要时管理 MMIO(,也是如此。
GPU 也有页表,因此如果 GPU 必须访问主内存,还必须创建这些页表。

您会看到,了解如何使用缓冲区非常重要。
要考虑的另一件事是 GPU 使用高度优化的内存格式 - 例如,用于表面的缓冲区可以描绘为内存的矩形区域。
纹理使用的缓冲区也是如此。但是,两者的存储方式不同:表面是线性存储的,每一行接
一行,而纹理缓冲区是平铺的(就像它由许多,例如,一个接一个线性存储的 16x16 表面组成(。
这使得采样和过滤速度更快。
此外,某些 GPU 可能需要在特定内存区域上具有纹理图像,在另一个区域中具有顶点缓冲区,依此类推。

因此,为图形驱动程序提供分配缓冲区时做出最佳选择所需的所有信息非常重要。

找到缓冲区后,驱动程序 (或 D3D 运行时( 将根据请求初始化缓冲区。
它可以通过复制数据或通过页表别名(如果音调允许(并最终使用某种形式的写入时复制来实现这一点。
但是,它这样做了,不再需要源数据(请参阅此处(。

CreateBuffer返回的COM对象是一个方便的代理,然后它被释放,这要归功于通常的comeAddRef/Release机制,它还要求图形驱动程序释放缓冲区。