diff --git a/source/Changelog.md b/source/Changelog.md index 7c3f5aa..b26f782 100644 --- a/source/Changelog.md +++ b/source/Changelog.md @@ -4,6 +4,14 @@ 此更新日志为纵览更新,对于具体文章的更新位于每个文章的开头的 `更新记录` 中。 ``` +## 2024/11/5 + +>* 更新`资源与内存`文档 + +## 2024/10/29 + +>* 更新`资源与内存`文档 + ## 2024/9/14 >* 更新`纵览`文档 diff --git a/source/Introduction.rst b/source/Introduction.rst index 7857a17..1b623a7 100644 --- a/source/Introduction.rst +++ b/source/Introduction.rst @@ -44,7 +44,7 @@ 图形接口 #################### -图形接口,也称图形 ``API`` ,其目的是定义一套规范用于与图形功能硬件设备进行沟通。由于市面上硬件设备产品众多每一家都可以定义一套自己设备的图形接口,这就会导致设备使用用户需要每一个设备单独适配,其工作了繁重重复不稳定, +图形接口,也称图形 ``API`` ,其目的是定义一套规范用于与图形功能硬件设备进行沟通。由于市面上硬件设备产品众多,每一家都可以定义一套自己设备的图形接口,这就会导致设备使用用户需要每一个设备单独适配,其工作了繁重重复不稳定, 所以硬件设备生产商联合起来定一个统一的图形接口,使用此接口可以与任何支持该接口的设备进行沟通。当今天下有四套图形标准: 1. ``OpenGL`` :隶属于 ``Khronos`` 组织 @@ -58,7 +58,7 @@ Khronos组织 ``Khronos`` 原本指代的是古希腊神话传说中掌管时间的神祗 ``克罗诺斯`` ,是俄耳甫斯教( ``Orphism`` )的原始神,此神祗经常与宙斯他爹 ``克洛诺斯`` ( ``Kronos`` ) 搞混,因为发音基本没区别。 虽然克罗诺斯和克洛诺斯都属于古希腊神话体系,但不是同一派别(可能类似于道教中的全真和正一)。在俄耳甫斯教中克罗诺斯被称为宇宙第一因或宇宙的源头(类似道家中的道生一)。 -扯远了。 `Khronos组织 `_ 是一家非常著名的开源标准规范组织,像大家熟知的 ``OpenGL`` 、 ``OpenCL`` 、 ``OpenGL`` 、 ``WebGL`` 还有 ``Vulkan`` 标准都是出自该组织。 +扯远了。 `Khronos组织 `_ 是一家非常著名的开源标准规范组织,像大家熟知的 ``OpenGL`` 、 ``OpenCL`` 、 ``SPIR`` 、 ``WebGL`` 还有 ``Vulkan`` 等等标准都是出自该组织。 OpenGL #################### @@ -77,7 +77,7 @@ Vulkan 作为新一代的图形 ``API`` ,可以说完全重新设计了架构,摒弃了 ``OpenGL`` 的基于上下文的架构执行指令,而是使用基于 ``CommandBuffer`` 指令缓存推送到设备工作 ``Queue`` 队列的方式,进行指令执行。支持 ``OpenGL`` 不支持的多线程和硬件光线追踪。在 ``OpenGL`` 中对于函数的获取, 有的用 ``GLEW`` 有的用 ``GLAD`` 有的函数获取在某些平台甚至都是么棱两可的, ``Vulkan`` 中规避了该诟病,使用统一的接口获取所有接口函数。明确绘制结果如何呈现,而不是像 ``OpenGL`` 那样有默认的颜色、深度缓存。等等,可以说 ``Vulkan`` 和 ``OpenGL`` 是完全不一样的, 硬要说 ``Vulkan`` 与 ``OpenGL`` 之间是什么关系,可以说 ``Vulkan`` 是将 ``OpenGL`` 中的很多原本由驱动负责的任务,现在将其开放出来由 ``Vulkan`` 开发者自己管理,这也就是为什么很多人觉得 ``Vulkan`` 困难的原因,使用 ``Vulkan`` 开发总有一种开发 ``OpenGL`` 驱动的感觉,但好处是架构清晰,性能优良,完全可以基于 ``Vulkan`` 去 -实现 ``OpenGL`` 的接口,反之则不行。要说 ``Vulkan`` 与 ``OpenGL`` 之间有什么相同点?确切说,除了图新学上统一的概念在 ``Vulkan`` 与 ``OpenGL`` 中是相同的(比如顶点属性,顶点着色器,片元着色器等等),其他没有任何相似的地方。读者完全 +实现 ``OpenGL`` 的接口,反之则不行。要说 ``Vulkan`` 与 ``OpenGL`` 之间有什么相同点?确切说,除了图形学上统一的概念在 ``Vulkan`` 与 ``OpenGL`` 中是相同的(比如顶点属性,顶点着色器,片元着色器等等),其他没有任何相似的地方。读者完全 可以把 ``Vulkan`` 当做全新的架构去学,不需要提前学完 ``OpenGL`` ,当然如果提前了解了 ``OpenGL`` ,对于 ``Vulkan`` 中的一些概念是相通的,会对理解起一些帮助。但是读者放心,您在学习本教程时不需要会 ``OpenGL`` 也可以理解其中的奥妙。 .. admonition:: ``Vulkan`` 与 ``DirectX 12`` diff --git a/source/Memory.rst b/source/Memory.rst index 480c0e1..acffef9 100644 --- a/source/Memory.rst +++ b/source/Memory.rst @@ -986,6 +986,8 @@ vkGetDeviceMemoryCommitment 通过之前 ``vkGetPhysicalDeviceMemoryProperties(...)`` 函数我们可以获取到设备的内存信息,现在我们就可以通过这些信息进行内存分配了。为此 ``Vulkan`` 为我们提供了 ``vkAllocateMemory(...)`` 函数进行内存分配。该函数定义如下: +.. _vk_Allocate_Memory: + vkAllocateMemory ---------------------------- diff --git a/source/PhysicalDevice.rst b/source/PhysicalDevice.rst index fc639cd..ea1acd4 100644 --- a/source/PhysicalDevice.rst +++ b/source/PhysicalDevice.rst @@ -62,6 +62,8 @@ vkEnumeratePhysicalDevices 枚举的 ``VkPhysicalDevice`` 句柄是在调用 ``vkCreateInstance(...)`` 创建 ``VkInstance`` 时驱动内部创建的。换句话说就是: ``VkPhysicalDevice`` 句柄的生命周期与 ``VkInstance`` 相同, ``VkInstance`` 创建 ``VkPhysicalDevice`` 句柄们也会创建, ``VkInstance`` 销毁 ``VkPhysicalDevice`` 句柄们也会销毁。 +.. _Get_Physical_Devicce_Properties: + 获取物理设备信息 ###################### @@ -167,6 +169,8 @@ VkPhysicalDeviceType 其中 ``VkPhysicalDeviceLimits`` 用于表述该设备的一些限制,比如最大支持的图片像素大小。 +.. _Vk_Physical_Device_Limits: + VkPhysicalDeviceLimits ************************* diff --git a/source/ResourceAndMemory.rst b/source/ResourceAndMemory.rst index 7a89e03..b56ef84 100644 --- a/source/ResourceAndMemory.rst +++ b/source/ResourceAndMemory.rst @@ -17,6 +17,8 @@ * 2024/5/21 更新 ``VkMemoryRequirements`` 章节。 * 2024/5/21 增加 ``资源与设备内存绑定`` 章节。 * 2024/9/6 更新 ``对应关系`` 章节。 + * 2024/10/29 更新 ``资源与设备内存绑定`` 章节。 + * 2024/11/5 更新 ``资源与设备内存绑定`` 章节。 在 `资源 <./Resource.html>`_ 章节中我们知道一个资源仅仅是一个 ``虚拟资源句柄`` ,其本质上并没有相应的内存实体用于存储数据。所以在创建完资源后,需要分配内存并与资源进行绑定,用于之后的数据读写。 @@ -209,6 +211,72 @@ VkMemoryRequirements 资源与设备内存绑定 ################## -.. note:: +通过之前的介绍,我们已经知道两件事: - 未完待续 \ No newline at end of file +* 如何在我们需要的设备内存上申请内存 +* 如何创建我们需要的资源 + +现在 ``资源`` 和 ``设备内存`` 都有了,接下来就可以将两者进行关联,即 ``绑定`` 。 + +``绑定`` 主要有两种: + +* ``缓存`` 与 ``设备内存`` 进行绑定。对应的接口为 ``vkBindBufferMemory(...)`` 。 +* ``图片`` 与 ``设备内存`` 进行绑定。对应的接口为 ``vkBindImageMemory(...)`` 。 + +接口定义如下: + +.. code-block:: c++ + + // 由 VK_VERSION_1_0 提供 + VkResult vkBindBufferMemory( + VkDevice device, + VkBuffer buffer, + VkDeviceMemory memory, + VkDeviceSize memoryOffset); + +* :bdg-secondary:`device` 对应的逻辑设备。 +* :bdg-secondary:`buffer` 对应绑定的缓存。 +* :bdg-secondary:`memory` 对应绑定的设备内存。 +* :bdg-secondary:`memoryOffset` 对应绑定的设备内存的相对偏移。 + +.. code-block:: c++ + + // 由 VK_VERSION_1_0 提供 + VkResult vkBindImageMemory( + VkDevice device, + VkImage image, + VkDeviceMemory memory, + VkDeviceSize memoryOffset); + +* :bdg-secondary:`device` 对应的逻辑设备。 +* :bdg-secondary:`image` 对应绑定的图片。 +* :bdg-secondary:`memory` 对应绑定的设备内存。 +* :bdg-secondary:`memoryOffset` 对应绑定的设备内存的相对偏移。 + +其中 ``buffer`` 、 ``memory`` 和 ``image`` 都需要从 ``device`` 中创建出来,这个不需要再赘述。这里主要需要说明一下 ``memoryOffset`` 参数的作用。 + +在 ``Vulkan`` 中其鼓励用户创建分配一块大的设备内存,不同的资源占用该设备内存不同的部分。这不仅能够最大化重复利用一块内存,优化内存使用率,也为用户制定自定义内存管理机制提供途径。这样设计的根本原因是: ``Vulkan`` 对于 ``VkDeviceMemory`` 创建的数量有 :bdg-danger:`上限` 。 + +在 :ref:`Get_Physical_Devicce_Properties` 章节中我们知道其内部有 :ref:`Vk_Physical_Device_Limits` 限制信息。其中有 ``maxMemoryAllocationCount`` 成员: + +.. code-block:: c++ + + // 由 VK_VERSION_1_0 提供s + typedef struct VkPhysicalDeviceLimits { + ... + uint32_t maxMemoryAllocationCount; + ... + } VkPhysicalDeviceLimits; + +* :bdg-secondary:`maxMemoryAllocationCount` 可通过 :ref:`vk_Allocate_Memory` 创建的最大同时存在的设备内存数量。且 ``Vulkan`` 要求该限制数量不能小于 ``4096`` + +.. figure:: ./_static/resource_bind_in_memory.png + + 设备内存与资源绑定示意图 + +当 ``vkBind[Buffer/Image]Memory(...)`` 函数返回 ``VkResult::VK_SUCCESS`` 说明只有躯壳的资源终于拥有了灵魂,它的一生完整了! + +.. admonition:: Vulkan 设备内存管理 + :class: note + + ``Vulkan`` 为用户自定义内存管理提供了可能,但实现一个高效稳健的内存管理系统并不是一件容易事。用户可以使用 ``AMD`` 在 ``GPU Open`` 计划中推出的 `Vulkan® Memory Allocator (VMA) `_ 进行设备内存管理。有关如何使用 ``VMA`` 将会在专门的章节中进行讲解。 \ No newline at end of file diff --git a/source/_static/resource_bind_in_memory.png b/source/_static/resource_bind_in_memory.png new file mode 100644 index 0000000..e404ddc Binary files /dev/null and b/source/_static/resource_bind_in_memory.png differ