バルカンウィンドウの窓面

みなさん、こんにちは、次はご紹介しますバルカン窓面を  。

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プラットフォーム、それはとりWIndowsHWNDHMODULEハンドル。したがって、特定のプラットフォームに適した拡張を提供することにWindowsようVK_KHR_win32_surface、それが自動的に含まれglfwGetRequiredInstanceExtensionsのリスト。

私たちは、作成するために、プラットフォーム固有の拡張機能を使用する方法を示しますWindowssurface橋が、実際のチュートリアルでは使用しません。クロスプラットフォーム依存のコードは意味を書いていないようなライブラリGLFWの回避を使用します。GLFW事実によるglfwCreateWindowSurface差プラットフォームの良い取引。もちろん、理想的には、特定の作業が完了する前に私たちを助けるためにそれらに依存することです、実現の背後にある外観は便利です。

フォームがあるためsurfaceであるVulkan埋める必要のある対象VkWin32SurfaceCreateInfoKHRの:構造を、2つの重要なパラメータがあるHWNDhInstanceははあなたが精通している場合は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に配置され、createInstnacesetupDebugCallback関数の後に。

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!");
    }
}

パラメータであるVkInstanceGLFWポインタの形、およびカスタム格納するためのディスペンサーVkSurfaceKHRの可変ポインタ。別のリターンのための統一されたプラットフォームVkResultGLFWこれは、破壊するために、専用の機能を提供していませんsurfaceが、単純にすることにより、VulkanオリジナルのAPI完了:

void cleanup() {
        ...
        vkDestroySurfaceKHR(instance, surface, nullptr);
        vkDestroyInstance(instance, nullptr);
        ...
    }

インスタンスが破棄される前に、きれいな面が完成する。最後に、確認してください。

第二に、お問い合わせは、サポート性を実証します

Vulkan統合された機能の実装がフォームをサポートするために、それはシステムがサポートすることで、各物理デバイスを意味するものではありません。したがって、我々は拡大する必要がisDeviceSuitable、機能をデバイスは、我々が作成した画像をレンダリングすることができることを確認してくださいsurfaceのではpresentation問題を解決するには、サポート見つけることですので、キューの特徴であるpresentationクラスタキューのキューを最終的に満たすために取得するには、surface作成する必要が。

現実には、サポートということであるgraphicsコマンドキューおよびクラスタのサポートpresentationコマンドキュークラスタが同じクラスタではないかもしれません。したがって、我々は変更する必要がありQueueFamilyIndi​​cesのストレージの分化を支持する構造を。

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;
}

サポートするために、という注意graphicspresentation機能性、当社の実際の環境が同じキュークラスタで得ることができる私たちのプログラム構造とデータ選択のロジックが続くために、それは、異なる場合がありますが、異なるクラスタからあるキューを処理していますので、私たちは統一両方のケースを扱うことができるということ。また、パフォーマンス上の理由から、我々はまた、明示的、物理的に使用される機器を指定するためのロジックを追加することができます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);

この例では、キューは、同じクラスタである、二つのハンドルは同じ値を有していてもよいです。

 

 

 

 

公開された53元の記事 ウォン称賛62 ビュー20000 +

おすすめ

転載: blog.csdn.net/u010281924/article/details/105369161