Skip to content

Commit

Permalink
Merge pull request #237 from spencer-lunarg/spencer-lunarg-external2
Browse files Browse the repository at this point in the history
Improve the External chapter
  • Loading branch information
gpx1000 authored Dec 25, 2023
2 parents 030f6db + 35bc24a commit 6a36cd5
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 63 deletions.
89 changes: 57 additions & 32 deletions chapters/extensions/external.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,27 @@ ifndef::images[:images: ../images/]

Sometimes not everything an application does related to the GPU is done in Vulkan. There are various situations where memory is written or read outside the scope of Vulkan. To support these use cases a set of external memory and synchronization functions was created

The list of extensions involved are:

* `VK_KHR_external_fence`
** Promoted to core in 1.1
* `VK_KHR_external_fence_capabilities`
** Promoted to core in 1.1
* `VK_KHR_external_memory`
** Promoted to core in 1.1
* `VK_KHR_external_memory_capabilities`
** Promoted to core in 1.1
* `VK_KHR_external_semaphore`
** Promoted to core in 1.1
* `VK_KHR_external_semaphore_capabilities`
** Promoted to core in 1.1
* `VK_KHR_external_fence_fd`
* `VK_KHR_external_fence_win32`
* `VK_KHR_external_memory_fd`
* `VK_KHR_external_memory_win32`
* `VK_KHR_external_semaphore_fd`
* `VK_KHR_external_semaphore_win32`
* `VK_ANDROID_external_memory_android_hardware_buffer`

This seems like a lot so let's break it down little by little.
== Extension breakdown

== Capabilities

The `VK_KHR_external_fence_capabilities`, `VK_KHR_external_semaphore_capabilities`, and `VK_KHR_external_memory_capabilities` are simply just ways to query information about what external support an implementation provides.
While there may seem to be a lot of `VK_KHR_external_*` extensions, they are in practice, just nicely separating the logic apart.

== Memory vs Synchronization

image::{images}extensions/external_extensions_2.png[external_extensions_2.png]

There is a set of extensions to handle the importing/exporting of just the memory itself. The other set extensions are for the synchronization primitives (`VkFence` and `VkSemaphore`) used to control internal Vulkan commands. It is common practice that for each piece of memory imported/exported there is also a matching fence/semaphore to manage the memory access.

=== Memory
== Handle Types

image::{images}extensions/external_extensions_1.png[external_extensions_1.png]

Depending on the platform there will be a specific handle used to communicate between Vulkan and the external platform. For example, POSIX `fd` are used for most non-Windows based platforms.

== Capabilities

The `VK_KHR_external_fence_capabilities`, `VK_KHR_external_semaphore_capabilities`, and `VK_KHR_external_memory_capabilities` are simply just ways to query information about what external support an implementation provides.

== External Memory

The `VK_KHR_external_memory` extension is mainly to provide the `VkExternalMemoryHandleTypeFlagBits` enum which describes the type of memory being used externally.

Expand All @@ -53,15 +41,52 @@ There are currently 3 supported ways to import/export memory

Each of these methods has their own detailed descriptions about limitations, requirements, ownership, etc.

==== Importing Memory
=== Importing Memory

To import memory, there is a `VkImport*Info` struct provided by the given external memory extension. This is passed into `vkAllocateMemory` where Vulkan will now have a `VkDeviceMemory` handle that maps to the imported memory.

==== Exporting Memory
[source,cpp]
----
// some external memory types require dedicated allocation
VkMemoryDedicatedAllocateInfo dedicated_info;
dedicated_info.buffer = buffer;
VkImportMemoryFdInfoKHR import_info;
import_info.pNext = &dedicated_info;
import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
import_info.fd = fd;
VkMemoryAllocateInfo allocate_info;
allocate_info.pNext = &import_info
VkDeviceMemory device_memory;
vkAllocateMemory(device, &allocate_info, nullptr, device_memory);
----

=== Exporting Memory

To export memory, there is a `VkGetMemory*` function provided by the given external memory extension. This function will take in a `VkDeviceMemory` handle and then map that to the extension exposed object.

=== Synchronization
[source,cpp]
----
VkExportMemoryAllocateInfo export_info;
export_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
VkMemoryAllocateInfo allocate_info;
allocate_info.pNext = &export_info
VkDeviceMemory device_memory;
vkAllocateMemory(device, &allocate_info, nullptr, device_memory);
VkMemoryGetFdInfoKHR get_handle_info;
get_handle_info.memory = device_memory;
get_handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
int fd;
vkGetMemoryFdKHR(device, &get_handle_info, &fd);
----

== Synchronization

External synchronization can be used in Vulkan for both `VkFence` and `VkSemaphores`. There is almost no difference between the two with regards to how it is used to import and export them.

Expand All @@ -74,11 +99,11 @@ There are currently 2 supported ways to import/export synchronization

Each extension explains how it manages ownership of the synchronization primitives.

==== Importing and Exporting Synchronization Primitives
=== Importing and Exporting Synchronization Primitives

There is a `VkImport*` function for importing and a `VkGet*` function for exporting. These both take the `VkFence`/`VkSemaphores` handle passed in along with the extension's method of defining the external synchronization object.

== Example
== Example Workflow

Here is a simple diagram showing the timeline of events between Vulkan and some other API talking to the GPU. This is used to represent a common use case for these external memory and synchronization extensions.

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 56 additions & 31 deletions lang/jp/chapters/extensions/external.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,27 @@ ifndef::chapters[:chapters: ../]

アプリケーションが GPU に関連して行うことのすべてが Vulkan で行われているわけではない場合があります。また、Vulkan の範囲外でメモリの書き込みや読み出しが行われる場合もあります。このようなユースケースのために、外部メモリの機能と同期の機能のセットが作成されました。

関係する拡張機能のリスト:

* `VK_KHR_external_fence`
** 1.1でコアに昇格
* `VK_KHR_external_fence_capabilities`
** 1.1でコアに昇格
* `VK_KHR_external_memory`
** 1.1でコアに昇格
* `VK_KHR_external_memory_capabilities`
** 1.1でコアに昇格
* `VK_KHR_external_semaphore`
** 1.1でコアに昇格
* `VK_KHR_external_semaphore_capabilities`
** 1.1でコアに昇格
* `VK_KHR_external_fence_fd`
* `VK_KHR_external_fence_win32`
* `VK_KHR_external_memory_fd`
* `VK_KHR_external_memory_win32`
* `VK_KHR_external_semaphore_fd`
* `VK_KHR_external_semaphore_win32`
* `VK_ANDROID_external_memory_android_hardware_buffer`

量が多いのでひとつずつ解説していきます。
== Extension breakdown

== 機能(Capabilities)

`VK_KHR_external_fence_capabilities`、`VK_KHR_external_semaphore_capabilities`、`VK_KHR_external_memory_capabilities` は、単に実装がどのような外部サポートを提供しているかという情報をクエリする方法です。
`VK_KHR_external_*` 拡張機能がたくさんあるように見えますが、実際にはうまく分離されています。

== メモリ vs 同期

image::../../../../chapters/images/extensions/external_extensions_2.png[external_extensions_2.png]

メモリ自体のインポート/エクスポートを処理する拡張機能セットがあります。もう一つの拡張機能セットは、Vulkan の内部コマンドを制御するための同期プリミティブ(`VkFence` と `VkSemaphore`)のためのものです。一般的には、インポート/エクスポートされるメモリの各部分には、メモリアクセスを管理するためのマッチするフェンス/セマフォもあります。

=== メモリ
== Handle Types

image::../../../../chapters/images/extensions/external_extensions_1.png[external_extensions_1.png]

プラットフォームによって、Vulkanと外部プラットフォーム間の通信に使用される特定の「ハンドル」があります。例えば、POSIXの `fd` は、ほとんどの非Windowsベースのプラットフォームで使用されます。

== 機能(Capabilities)

`VK_KHR_external_fence_capabilities`、`VK_KHR_external_semaphore_capabilities`、`VK_KHR_external_memory_capabilities` は、単に実装がどのような外部サポートを提供しているかという情報をクエリする方法です。

== メモリ

`VK_KHR_external_memory` 拡張機能は、主に外部で使用されているメモリのタイプを記述する `VkExternalMemoryHandleTypeFlagBits` 列挙型を提供します。

Expand All @@ -52,15 +40,52 @@ ifndef::chapters[:chapters: ../]

これらのメソッドにはそれぞれ、制限、要件、所有権などに関する詳細な説明があります。

==== メモリのインポート
=== メモリのインポート

メモリをインポートするには、与えられた外部メモリ拡張機能によって提供される `VkImport*Info` 構造体があります。これが `vkAllocateMemory` に渡され、Vulkan はインポートされたメモリにマップする `VkDeviceMemory` ハンドルを持つことになります。

==== メモリのエクスポート
[source,cpp]
----
// 外部メモリの種類によっては、専用の割り当てが必要
VkMemoryDedicatedAllocateInfo dedicated_info;
dedicated_info.buffer = buffer;
VkImportMemoryFdInfoKHR import_info;
import_info.pNext = &dedicated_info;
import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
import_info.fd = fd;
VkMemoryAllocateInfo allocate_info;
allocate_info.pNext = &import_info
VkDeviceMemory device_memory;
vkAllocateMemory(device, &allocate_info, nullptr, device_memory);
----

=== メモリのエクスポート

メモリをエクスポートするには、与えられた外部メモリ拡張機能によって提供される `VkGetMemory*` 関数があります。この関数は、`VkDeviceMemory` のハンドルを受け取り、それを拡張機能が公開しているオブジェクトにマッピングします。

=== 同期
[source,cpp]
----
VkExportMemoryAllocateInfo export_info;
export_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
VkMemoryAllocateInfo allocate_info;
allocate_info.pNext = &export_info
VkDeviceMemory device_memory;
vkAllocateMemory(device, &allocate_info, nullptr, device_memory);
VkMemoryGetFdInfoKHR get_handle_info;
get_handle_info.memory = device_memory;
get_handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
int fd;
vkGetMemoryFdKHR(device, &get_handle_info, &fd);
----

== 同期

外部同期はVulkanでは `VkFence` と `VkSemaphores` の両方で使用できます。両者のインポート/エクスポートの方法に関しては、ほとんど違いはありません。

Expand All @@ -73,7 +98,7 @@ ifndef::chapters[:chapters: ../]

各拡張機能は、同期プリミティブの所有権をどのように管理するかを説明します。

==== 同期プリミティブのインポートとエクスポート
=== 同期プリミティブのインポートとエクスポート

インポートするための `VkImport*` 関数と、エクスポートするための `VkGet*` 関数があります。これらはどちらも `VkFence` / `VkSemaphores` のハンドルが渡され、外部同期オブジェクトを定義する拡張機能のメソッドを受け取ります。

Expand Down

0 comments on commit 6a36cd5

Please sign in to comment.