みなさん、こんにちは、次はご紹介しますバルカン窓面を 。
Vulkan
関連した自由なプラットフォーム機能であるAPI
コレクション。これは、ウィンドウシステムと直接対話することはできません。結果は画面に提示されているレンダリングするためには、あなたが確立する必要があるVulkan
ウィンドウシステム間の接続を、我々は使用する必要がありますWSI
拡張子(システムインテグレーションの形式)。このセクションでは、我々は、最初にその説明しますVK_KHR_surfaceを。これは、公開さVkSurfaceKHRをそれが表す、surface
使用にレンダリングされた画像を提示するために、抽象の種類を。私たちはするプログラムで使用するsurface
当社すでにによって導入されるGLFW
支援のそれに関連するオープンな形に拡張します。簡単に言えば表面は、ブリッジバルカンシステムを形成するように接続されています。
VK_KHR_surfaceの拡張子は、これまでのところ、我々はそれが有効に持っていた、それが中に含まれ、インスタンス・レベルの拡張であるglfwGetRequiredInstanceExtensions返されるリスト。リストには、他のWSI拡張の数は次の数のパネルに使用されます含まれています。
あなたはする必要がありinstance
、作成後すぐにフォームを作成しsurface
、それは物理的なデバイスの選択に影響しますので、。このセクションでは、う理由surface
議論に含まれるロジックを作成するには、フォームのでれるsurface
レンダリングのため、プレゼンテーションでは、この部分に参加する物理デバイスを作成時期尚早場合、基本的な物理デバイスの設定作業を混乱させるだろう、比較的大きな問題です。また、フォームsurface
に自体Vulkan
も必須ではありません。Vulkan
そうすることを許可され、それは同じ必要はありませんOpenGL
フォームを作成する必要があるとしてsurface
。
まず、窓面を作成します
今すぐフォームの作成に着手しsurface
、クラスメンバdebugCallback
の下に変数のメンバーに参加するサーフェスを。
VkSurfaceKHR surface;
がVkSurfaceKHRのオブジェクトとその使用は、プラットフォームに関連付けられているが、詳細はシステムの特定のフォームの作成に頼る必要はありません。例えば、ではWindows
プラットフォーム、それはとりWIndows
にHWNDとHMODULEハンドル。したがって、特定のプラットフォームに適した拡張を提供することにWindows
ようVK_KHR_win32_surface、それが自動的に含まれglfwGetRequiredInstanceExtensionsのリスト。
私たちは、作成するために、プラットフォーム固有の拡張機能を使用する方法を示しますWindows
にsurface
橋が、実際のチュートリアルでは使用しません。クロスプラットフォーム依存のコードは意味を書いていないようなライブラリGLFWの回避を使用します。GLFW
事実によるglfwCreateWindowSurface差プラットフォームの良い取引。もちろん、理想的には、特定の作業が完了する前に私たちを助けるためにそれらに依存することです、実現の背後にある外観は便利です。
フォームがあるためsurface
であるVulkan
埋める必要のある対象VkWin32SurfaceCreateInfoKHRの:構造を、2つの重要なパラメータがあるHWNDとhInstanceはは。あなたが精通している場合はwindows
、開発中のあなたは、これらのウィンドウハンドルとプロセスであることを知っている必要があります。
VkWin32SurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
createInfo.hwnd = glfwGetWin32Window(window);
createInfo.hinstance = GetModuleHandle(nullptr);
glfwGetWin32Windowの機能はGLFWから元のフォームオブジェクト取得するために使用されるHWNDを。GetModuleHandle関数は、現在のプロセスを返しHINSTANCEのハンドルを。
充填構造が完了した後は、使用することができますvkCreateWin32SurfaceKHRが表面ブリッジを作成し、破棄、作成取得する前にDebugReportCallEXTをここと、同じ必要がしinstance
得る作成surface
機能で。ここに関与パラメータでありinstance
、 surface
情報作成、カスタムアロケータ、最終的に保存surface
ハンドル変数が。
auto CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR) vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR");
if (!CreateWin32SurfaceKHR || CreateWin32SurfaceKHR(instance, &createInfo, nullptr, &surface) != VK_SUCCESS) {
throw std::runtime_error("failed to create window surface!");
}
このプロセスは、例えば、他のプラットフォームと同様でありLinux
、X11インタフェースウィンドウシステムを使用して、vkCreateXcbSurfaceKHR接続機能を確立します。
glfwCreateWindowSurfaceの異なるプラットフォームの違いに応じて機能は、実装の詳細に異なるものになります。私たちは今、私たちのプログラムに統合されます。initVulkan機能の追加CreateSurfaceに配置され、createInstnaceとsetupDebugCallback関数の後に。
void initVulkan() {
createInstance();
setupDebugCallback();
createSurface();
pickPhysicalDevice();
createLogicalDevice();
}
void createSurface() {
}
GLFW
構造を使用しますが、呼び出し元の関数に渡された非常に直接的なパラメータを選択しないでください。
void createSurface() {
if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) {
throw std::runtime_error("failed to create window surface!");
}
}
パラメータであるVkInstance、GLFW
ポインタの形、およびカスタム格納するためのディスペンサーVkSurfaceKHRの可変ポインタ。別のリターンのための統一されたプラットフォームVkResult。GLFW
これは、破壊するために、専用の機能を提供していませんsurface
が、単純にすることにより、Vulkan
オリジナルのAPI
完了:
void cleanup() {
...
vkDestroySurfaceKHR(instance, surface, nullptr);
vkDestroyInstance(instance, nullptr);
...
}
インスタンスが破棄される前に、きれいな面が完成する。最後に、確認してください。
第二に、お問い合わせは、サポート性を実証します
がVulkan
統合された機能の実装がフォームをサポートするために、それはシステムがサポートすることで、各物理デバイスを意味するものではありません。したがって、我々は拡大する必要がisDeviceSuitable、機能をデバイスは、我々が作成した画像をレンダリングすることができることを確認してくださいsurface
。のではpresentation
問題を解決するには、サポート見つけることですので、キューの特徴であるpresentation
クラスタキューのキューを最終的に満たすために取得するには、surface
作成する必要が。
現実には、サポートということであるgraphics
コマンドキューおよびクラスタのサポートpresentation
コマンドキュークラスタが同じクラスタではないかもしれません。したがって、我々は変更する必要がありQueueFamilyIndicesのストレージの分化を支持する構造を。
struct QueueFamilyIndices {
int graphicsFamily = -1;
int presentFamily = -1;
bool isComplete() {
return graphicsFamily >= 0 && presentFamily >= 0;
}
};
次に、我々は、変更findQueueFamiliesがで見つけるために機能するpresentation
キューのクラスタ機能。コアコードは、機能確認するために使用されるvkGetPhysicalDeviceSurfaceSupportKHR、その物理デバイス、キューおよびクラスタインデックスをsurface
パラメータとして。でVK_QUEUE_GRAPHICS_BIT同じループ内の関数への呼び出しを追加します。
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
そして、必要がブール値をチェックしに格納するpresentation
キュークラスタ化インデックス:
if (queueFamily.queueCount > 0 && presentSupport) {
indices.presentFamily = i;
}
サポートするために、という注意graphics
とpresentation
機能性、当社の実際の環境が同じキュークラスタで得ることができる私たちのプログラム構造とデータ選択のロジックが続くために、それは、異なる場合がありますが、異なるクラスタからあるキューを処理していますので、私たちは統一両方のケースを扱うことができるということ。また、パフォーマンス上の理由から、我々はまた、明示的、物理的に使用される機器を指定するためのロジックを追加することができますgraphics
し、presentation
同じクラスタキューから関数を。
第三に、プレゼンテーションキューを作成
残りのものは、論理デバイスの作成プロセスを作成することです変更することでpresentation
キューを取得し、VkQueueのハンドルを。キューハンドルのメンバ変数のセーブ追加します。
VkQueue presentQueue;
次に、我々はより多く必要VkDeviceQueueCreateInfoの異なる機能を持つキューを作成するために構造を。エレガントな方法は、異なる機能のクラスターのキュークラスタのためのキューの一意性を保証するために、設定されたコレクションを作成することです:
#include <set>
...
QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
std::set<int> uniqueQueueFamilies = {indices.graphicsFamily, indices.presentFamily};
float queuePriority = 1.0f;
for (int queueFamily : uniqueQueueFamilies) {
VkDeviceQueueCreateInfo queueCreateInfo = {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = queueFamily;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority;
queueCreateInfos.push_back(queueCreateInfo);
}
しかし、また、変更VkDeviceCreateInfoのキューのポイントセットを:
createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
createInfo.pQueueCreateInfos = queueCreateInfos.data();
キューが同じクラスタであれば、我々は時間のインデックスを渡す必要があります。最後に、キューハンドルを取得するための呼び出しを追加します。
vkGetDeviceQueue(device, indices.presentFamily, 0, &presentQueue);
この例では、キューは、同じクラスタである、二つのハンドルは同じ値を有していてもよいです。