Skip to content

Latest commit

 

History

History
137 lines (96 loc) · 8.16 KB

protected.adoc

File metadata and controls

137 lines (96 loc) · 8.16 KB

保護されたメモリ

デバイスメモリは「保護されたデバイスメモリ」と「保護されていないデバイスメモリ」に分けられます。

ほとんどの OS は、明示的に共有(たとえば 外部メモリ を介して)されていない限り、あるアプリケーションが別のアプリケーションの GPU メモリにアクセスすることを許可しません。保護されたメモリの一般的な例は、DRM コンテンツを格納するためのものです。プロセスは、(イメージフィルタリング、再生コントロールやクローズドキャプションの合成などのために)変更を許可されるかもしれませんが、保護されていないメモリに抽出することはできません。データは暗号化されて送られ、ディスプレイ上のピクセルに届くまで暗号化されたままです。

Vulkan Spec では、「保護されたデバイスメモリ」が実行することを詳しく説明しています。以下では、保護されたメモリを使用して保護されたサブミットを適切に有効化するために必要なことを示します。

対応の確認

保護されたメモリは Vulkan 1.1で追加されたもので、それ以前には拡張機能もありませんでした。つまり、Vulkan 1.0のデバイスは、保護されたメモリをサポートしていません。対応を確認するには、VkPhysicalDeviceProtectedMemoryFeatures::protectedMemory フィールドをクエリして有効にする必要があります。

保護されたキュー

保護されたキューは、保護されたメモリと保護されていないメモリの両方を読むことができますが、保護されたメモリにのみ書き込むことができます。キューが保護されていないメモリへの書き込みが可能な場合、保護されたメモリからの読み込みもできません。

Note

サイドチャネル攻撃を防ぐために、保護されたキューでは、パフォーマンスカウンタやその他のタイミング測定システムが無効になったり、精度が低くなったりすることがあります。

各キューの VkQueueFlags を取得するために vkGetPhysicalDeviceQueueFamilyProperties を使用すると、VK_QUEUE_PROTECTED_BIT フラグが公開されているキューファミリを見つけることができます。これは、そのファミリからのキューが常に保護されていることを意味するのではなく、そのキューが保護されたキューになれることを意味しています。

ドライバに VkQueue の保護を指示するためには、vkCreateDevice の際に VkDeviceQueueCreateInfoVK_DEVICE_QUEUE_CREATE_PROTECTED_BIT が必要となります。

以下の疑似コードは、同じキューファミリから保護された VkQueue オブジェクトを2つ作成する方法です。

VkDeviceQueueCreateInfo queueCreateInfo[1];
queueCreateInfo[0].flags             = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
queueCreateInfo[0].queueFamilyIndex  = queueFamilyFound;
queueCreateInfo[0].queueCount        = 2; // 2つのキューがキューファミリに入っていると仮定する

VkDeviceCreateInfo deviceCreateInfo   = {};
deviceCreateInfo.pQueueCreateInfos    = queueCreateInfo;
deviceCreateInfo.queueCreateInfoCount = 1;
vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &deviceHandle);

また、キューファミリ内のキューを分割して、一部は保護され、一部は保護されないようにすることも可能です。以下の疑似コードは、同じキューファミリから、保護された VkQueue オブジェクト1つと保護されていない VkQueue オブジェクト1つを作成する方法です。

VkDeviceQueueCreateInfo queueCreateInfo[2];
queueCreateInfo[0].flags             = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
queueCreateInfo[0].queueFamilyIndex  = queueFamilyFound;
queueCreateInfo[0].queueCount        = 1;

queueCreateInfo[1].flags             = 0; // 保護フラグが設定していないため保護されない
queueCreateInfo[1].queueFamilyIndex  = queueFamilyFound;
queueCreateInfo[1].queueCount        = 1;

VkDeviceCreateInfo deviceCreateInfo   = {};
deviceCreateInfo.pQueueCreateInfos    = queueCreateInfo;
deviceCreateInfo.queueCreateInfoCount = 2;
vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &deviceHandle);

現在、VkQueue ハンドルを取得する際に VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT フラグを渡すために、vkGetDeviceQueue ではなく vkGetDeviceQueue2 を使用する必要があります。

VkDeviceQueueInfo2 info = {};
info.queueFamilyIndex = queueFamilyFound;
info.queueIndex       = 0;
info.flags            = VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT;
vkGetDeviceQueue2(deviceHandle, &info, &protectedQueue);

保護されたリソース

VkImageVkBuffer を保護するには、作成時にそれぞれ VK_IMAGE_CREATE_PROTECTED_BITVK_BUFFER_CREATE_PROTECTED_BIT を設定するだけです。

保護されたリソースにメモリをバインドする場合、VkDeviceMemoryVK_MEMORY_PROPERTY_PROTECTED_BIT ビットを持つ VkMemoryType から割り当てられたものでなければなりません。

保護されたスワップチェーン

保護されたスワップチェーンを作成するには、VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR ビットを使用します。

保護されたスワップチェーンから vkGetSwapchainImagesKHR で取得したすべての VkImage は、VK_IMAGE_CREATE_PROTECTED_BIT で作成された場合と同じものになります。

VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR フラグが設定されている状態でスワップチェーンを作成できるかどうか不明な場合があります。VK_KHR_surface_protected_capabilities 拡張機能は、これが不明な可能性があるプラットフォームで公開されています。

保護されたコマンドバッファ

保護された VkQueue を使用して、VkCommandPool を作成する際に VK_COMMAND_POOL_CREATE_PROTECTED_BIT を指定することもできます。

VkCommandPoolCreateInfo info = {};
info.flags            = VK_COMMAND_POOL_CREATE_PROTECTED_BIT;
info.queueFamilyIndex = queueFamilyFound; // 保護されたキュー
vkCreateCommandPool(deviceHandle, &info, nullptr, &protectedCommandPool);

保護されたコマンドプールから割り当てられたすべてのコマンドバッファは、「保護されたコマンドバッファ」となります。

VkCommandBufferAllocateInfo info = {};
info.commandPool = protectedCommandPool;
vkAllocateCommandBuffers(deviceHandle, &info, &protectedCommandBuffers);

保護された仕事のサブミット

保護されるべき仕事をサブミットするときは、サブミットされたすべての VkCommandBuffer も保護されていなければなりません。

VkProtectedSubmitInfo protectedSubmitInfo = {};
protectedSubmitInfo.protectedSubmit       = true;

VkSubmitInfo submitInfo                  = {};
submitInfo.pNext                         = &protectedSubmitInfo;
submitInfo.pCommandBuffers               = protectedCommandBuffers;

vkQueueSubmit(protectedQueue, 1, &submitInfo, fence));

または、VK_KHR_synchronization2 を使用します。

VkSubmitInfo2KHR submitInfo = {}
submitInfo.flags = VK_SUBMIT_PROTECTED_BIT_KHR;

vkQueueSubmit2KHR(protectedQueue, 1, submitInfo, fence);