diff --git a/vulkanLearn/src/02.cpp b/vulkanLearn/src/02.cpp new file mode 100644 index 0000000..d18b03b --- /dev/null +++ b/vulkanLearn/src/02.cpp @@ -0,0 +1,181 @@ +#include "external/vulkan.h" +#include "com/Window.h" +#include "01 Instance and Devices/03 Connecting with a Vulkan Loader library.h" +#include "01 Instance and Devices/05 Loading function exported from a Vulkan Loader library.h" +#include "01 Instance and Devices/06 Loading global-level functions.h" +#include "01 Instance and Devices/07 Checking available Instance extensions.h" +#include <01 Instance and Devices/09 Loading instance-level functions.h> +#include <01 Instance and Devices/10 Enumerating available physical devices.h> +#include <01 Instance and Devices/12 Getting features and properties of a physical device.h> +#include <01 Instance and Devices/14 Selecting index of a queue family with desired capabilities.h> +#include <01 Instance and Devices/16 Loading device-level functions.h> +#include <01 Instance and Devices/17 Getting a device queue.h> +#include <01 Instance and Devices/19 Destroying a logical device.h> +#include <01 Instance and Devices/20 Destroying a Vulkan Instance.h> +#include <01 Instance and Devices/21 Releasing a Vulkan Loader library.h> + +#include "02 Image Presentation/01 Creating a Vulkan Instance with WSI extensions enabled.h" +#include "02 Image Presentation/02 Creating a presentation surface.h" +#include "02 Image Presentation/03 Selecting a queue family that supports presentation to a given surface.h" +#include <02 Image Presentation/04 Creating a logical device with WSI extensions enabled.h> +#include <02 Image Presentation/05 Selecting a desired presentation mode.h> +#include <02 Image Presentation/06 Getting capabilities of a presentation surface.h> +#include <02 Image Presentation/07 Selecting a number of swapchain images.h> +#include <02 Image Presentation/08 Choosing a size of swapchain images.h> +#include <02 Image Presentation/09 Selecting desired usage scenarios of swapchain images.h> +#include <02 Image Presentation/10 Selecting a transformation of swapchain images.h> +#include <02 Image Presentation/11 Selecting a format of swapchain images.h> +#include <02 Image Presentation/12 Creating a swapchain.h> +#include <02 Image Presentation/13 Getting handles of swapchain images.h> +#include <02 Image Presentation/14 Creating a swapchain with R8G8B8A8 format and a MAILBOX present mode.h> +#include <02 Image Presentation/15 Acquiring a swapchain image.h> +#include <02 Image Presentation/16 Presenting an image.h> +#include <02 Image Presentation/17 Destroying a swapchain.h> +#include <02 Image Presentation/18 Destroying a presentation surface.h> +#include <03 Command Buffers and Synchronization/07 Creating a semaphore.h> +#include <03 Command Buffers and Synchronization/08 Creating a fence.h> +using namespace VulkanCookbook; + +Window* pWnd; +//创建窗口 +WindowParameters createWindow() { + WindowParameters window_parameters{}; + pWnd = new Window(600, 800, "hello Window"); + window_parameters.HWnd = pWnd->GetHWnd(); + window_parameters.HInstance = Window::WindowClass::GetInstance(); + return window_parameters; +} +int main02() { + //加载dll + LIBRARY_TYPE vulkan_library; + ConnectWithVulkanLoaderLibrary(vulkan_library); + + //加载vulkan接口 + LoadFunctionExportedFromVulkanLoaderLibrary(vulkan_library); + + //调用vulkan接口,加载全局函数指针 + LoadGlobalLevelFunctions(); + { + //调用全局函数指针,检查实例扩展 + std::vector available_extensions; + CheckAvailableInstanceExtensions(available_extensions); + } + + //调用全局接口,创建实例 + std::vector desired_extensions; + char* application_name = "hello world"; + VkInstance instance; + CreateVulkanInstanceWithWsiExtensionsEnabled(desired_extensions, application_name, instance); + + //调用vulkan接口,加载实例函数指针 + LoadInstanceLevelFunctions(instance, desired_extensions); + //调用实例接口,获取物理设备列表 + std::vector available_devices; + EnumerateAvailablePhysicalDevices(instance, available_devices); + VkPhysicalDevice physical_device = available_devices[0]; + + //调用实例接口,检查物理设备功能 + VkPhysicalDeviceFeatures device_features; + VkPhysicalDeviceProperties device_properties; + GetFeaturesAndPropertiesOfPhysicalDevice(physical_device, device_features, device_properties); + + //调用实例接口,获取命令队列信息 + uint32_t graphics_queue_family_index, compute_queue_family_index; + SelectIndexOfQueueFamilyWithDesiredCapabilities(physical_device, VK_QUEUE_GRAPHICS_BIT, graphics_queue_family_index); + SelectIndexOfQueueFamilyWithDesiredCapabilities(physical_device, VK_QUEUE_COMPUTE_BIT, compute_queue_family_index); + + std::vector requested_queues = { { graphics_queue_family_index, { 1.0f } } }; + if (graphics_queue_family_index != compute_queue_family_index) { + requested_queues.push_back({ compute_queue_family_index, { 1.0f } }); + } + //调用实例接口,创建逻辑设备,并且检查是否支持交换链 + VkDevice logical_device; + desired_extensions.clear(); + CreateLogicalDeviceWithWsiExtensionsEnabled(physical_device, requested_queues, desired_extensions, &device_features, logical_device); + + //调用vulkan接口,加载设备函数指针 + LoadDeviceLevelFunctions(logical_device, desired_extensions); + + WindowParameters&& window_parameters = createWindow(); + VkSurfaceKHR presentation_surface; + //调用实例接口,创建图像显示设备,需要传递窗口,并启用对应扩展 + CreatePresentationSurface(instance, window_parameters, presentation_surface); + + //调用实例接口,寻找支持与图像显示设备通信的命令队列 + uint32_t queue_family_index; + SelectQueueFamilyThatSupportsPresentationToGivenSurface(physical_device, presentation_surface, queue_family_index); + + //调用实例接口,查询图像显示设备的显示模式 + VkPresentModeKHR present_mode; + SelectDesiredPresentationMode(physical_device, presentation_surface, VK_PRESENT_MODE_MAILBOX_KHR, present_mode); + + //调用实例接口,查询图像显示设备的显示能力 + VkSurfaceCapabilitiesKHR surface_capabilities; + GetCapabilitiesOfPresentationSurface(physical_device, presentation_surface, surface_capabilities); + + //获取交换链图片数量 + uint32_t number_of_images; + SelectNumberOfSwapchainImages(surface_capabilities, number_of_images); + //获取交换链图片尺寸 + VkExtent2D size_of_images; + ChooseSizeOfSwapchainImages(surface_capabilities, size_of_images); + + //选择交换链图像的使用场景:渲染目标、深度模板 + VkImageUsageFlags image_usage; + SelectDesiredUsageScenariosOfSwapchainImages(surface_capabilities, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, image_usage); + + //选择交换链在屏幕上的空间变换 + VkSurfaceTransformFlagBitsKHR surface_transform; + SelectTransformationOfSwapchainImages(surface_capabilities, VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, surface_transform); + + //选择交换链图像的格式与颜色空间 + VkFormat image_format; + VkColorSpaceKHR image_color_space; + SelectFormatOfSwapchainImages(physical_device, presentation_surface, { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }, + image_format, image_color_space); + + //调用设备接口,创建交换链 + VkSwapchainKHR old_swapchain = VK_NULL_HANDLE, swapchain; + CreateSwapchain(logical_device, presentation_surface, number_of_images, { image_format, image_color_space }, size_of_images + ,image_usage, surface_transform, present_mode, old_swapchain, swapchain); + + //调用设备接口,获取交换链图像句柄 + std::vector swapchain_images; + GetHandlesOfSwapchainImages(logical_device, swapchain, swapchain_images); + + //创建指定格式的交换链 + old_swapchain = swapchain; + CreateSwapchainWithR8G8B8A8FormatAndMailboxPresentMode(physical_device, presentation_surface, logical_device + , image_usage, size_of_images, image_format, old_swapchain , swapchain, swapchain_images); + + //调用设备接口,创建围栏,用于同步命令 + VkFence fence; + CreateFence(logical_device, false, fence); + + //调用设备接口,获取当前交换链图像编号 + uint32_t image_index; + AcquireSwapchainImage(logical_device, swapchain, nullptr , fence, image_index); + + //调用设备接口,获取命令队列 + VkQueue graphics_queue, compute_queue; + GetDeviceQueue(logical_device, graphics_queue_family_index, 0, graphics_queue); + GetDeviceQueue(logical_device, compute_queue_family_index, 0, compute_queue); + + //显示图像 + std::vector rendering_semaphores; + std::vector images_to_present; + PresentImage(graphics_queue, rendering_semaphores, images_to_present); + + //调用设备接口,销毁交换链 + DestroySwapchain(logical_device, swapchain); + //调用实例接口,销毁显示曲面(屏幕) + DestroyPresentationSurface(instance, presentation_surface); + + //调用设备接口,销毁逻辑设备 + DestroyLogicalDevice(logical_device); + //调用实例接口,销毁vulkan实例1 + DestroyVulkanInstance(instance); + //调用系统接口,销毁dll + ReleaseVulkanLoaderLibrary(vulkan_library); + return 1; +} \ No newline at end of file diff --git a/vulkanLearn/src/com/Window.cpp b/vulkanLearn/src/com/Window.cpp index 8946e8b..6a5639d 100644 --- a/vulkanLearn/src/com/Window.cpp +++ b/vulkanLearn/src/com/Window.cpp @@ -1,36 +1,15 @@ -/****************************************************************************************** -* Chili Direct3D Engine * -* Copyright 2018 PlanetChili * -* * -* This file is part of Chili Direct3D Engine. * -* * -* Chili Direct3D Engine is free software: you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* The Chili Direct3D Engine is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with The Chili Direct3D Engine. If not, see . * -******************************************************************************************/ #include "Window.h" -#include -#pragma comment (lib,"user32.lib") - // Window Class Stuff -WindowClass WindowClass::wndClass; +Window::WindowClass Window::WindowClass::wndClass; -WindowClass::WindowClass() noexcept +Window::WindowClass::WindowClass() noexcept : hInst( GetModuleHandle( nullptr ) ) { WNDCLASSEX wc = { 0 }; wc.cbSize = sizeof( wc ); wc.style = CS_OWNDC; + wc.lpfnWndProc = HandleMsgSetup; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = GetInstance(); @@ -39,20 +18,97 @@ WindowClass::WindowClass() noexcept wc.lpszMenuName = nullptr; wc.lpszClassName = GetName(); RegisterClassEx( &wc ); - } -WindowClass::~WindowClass() +Window::WindowClass::~WindowClass() { - UnregisterClass( wndClassName,GetInstance() ); + } -const char* WindowClass::GetName() noexcept +const char* Window::WindowClass::GetName() noexcept { return wndClassName; } -HINSTANCE WindowClass::GetInstance() noexcept +HINSTANCE Window::WindowClass::GetInstance() noexcept { return wndClass.hInst; -} \ No newline at end of file +} +Window::Window(int width, int height, const char* name) + :width(width),height(height) +{ + RECT wr{}; + wr.left = 100; + wr.right = width + wr.left; + wr.top = 100; + wr.bottom = height + wr.top; + hWnd = CreateWindow( + WindowClass::GetName(), name, + WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, + CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top, + nullptr, nullptr, WindowClass::GetInstance(), this + ); + ShowWindow(hWnd, SW_SHOWDEFAULT); +} +bool Window::ProcessMessages(int& code) +{ + MSG msg; + // while queue has messages, remove and dispatch them (but do not block on empty queue) + while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) + { + // check for quit because peekmessage does not signal this via return val + if (msg.message == WM_QUIT) + { + // return optional wrapping int (arg to PostQuitMessage is in wparam) signals quit + code = (int)msg.wParam; + return true; + } + + // TranslateMessage will post auxilliary WM_CHAR messages from key msgs + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return false; +} +LRESULT CALLBACK Window::HandleMsgSetup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept +{ + // use create parameter passed in from CreateWindow() to store window class pointer at WinAPI side + if (msg == WM_NCCREATE) + { + // extract ptr to window class from creation data + const CREATESTRUCTW* const pCreate = reinterpret_cast(lParam); + Window* const pWnd = static_cast(pCreate->lpCreateParams); + // set WinAPI-managed user data to store ptr to window instance + SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast(pWnd)); + // set message proc to normal (non-setup) handler now that setup is finished + SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(&Window::HandleMsgThunk)); + // forward message to window instance handler + return pWnd->HandleMsg(hWnd, msg, wParam, lParam); + } + // if we get a message before the WM_NCCREATE message, handle with default handler + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +LRESULT CALLBACK Window::HandleMsgThunk(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept +{ + // retrieve ptr to window instance + Window* const pWnd = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + // forward message to window instance handler + return pWnd->HandleMsg(hWnd, msg, wParam, lParam); +} + +LRESULT Window::HandleMsg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept +{ + switch (msg) + { + // we don't want the DefProc to handle this message because + // we want our destructor to destroy the window, so return 0 instead of break + case WM_CLOSE: + PostQuitMessage(0); + return 0; + // clear keystate when window loses focus to prevent input getting "stuck" + /************** END MOUSE MESSAGES **************/ + } + + return DefWindowProc(hWnd, msg, wParam, lParam); +} diff --git a/vulkanLearn/src/com/Window.h b/vulkanLearn/src/com/Window.h index 9439c22..477622e 100644 --- a/vulkanLearn/src/com/Window.h +++ b/vulkanLearn/src/com/Window.h @@ -1,36 +1,33 @@ -/****************************************************************************************** -* Chili Direct3D Engine * -* Copyright 2018 PlanetChili * -* * -* This file is part of Chili Direct3D Engine. * -* * -* Chili Direct3D Engine is free software: you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation, either version 3 of the License, or * -* (at your option) any later version. * -* * -* The Chili Direct3D Engine is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with The Chili Direct3D Engine. If not, see . * -******************************************************************************************/ #pragma once #include -// singleton manages registration/cleanup of window class -class WindowClass +class Window { public: - static const char* GetName() noexcept; - static HINSTANCE GetInstance() noexcept; + Window(int width, int height, const char* name); + HWND GetHWnd() { + return hWnd; + } + static bool ProcessMessages(int& code); + + class WindowClass + { + public: + static const char* GetName() noexcept; + static HINSTANCE GetInstance() noexcept; + private: + WindowClass() noexcept; + ~WindowClass(); + WindowClass(const WindowClass&) = delete; + WindowClass& operator=(const WindowClass&) = delete; + static constexpr const char* wndClassName = "MainWnd"; + static WindowClass wndClass; + HINSTANCE hInst; + }; private: - WindowClass() noexcept; - ~WindowClass(); - WindowClass(const WindowClass&) = delete; - WindowClass& operator=(const WindowClass&) = delete; - static constexpr const char* wndClassName = "Chili Direct3D Engine Window"; - static WindowClass wndClass; - HINSTANCE hInst; + static LRESULT CALLBACK HandleMsgSetup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept; + static LRESULT CALLBACK HandleMsgThunk(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept; + LRESULT HandleMsg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept; + int width; + int height; + HWND hWnd; }; \ No newline at end of file diff --git a/vulkanLearn/xmake.lua b/vulkanLearn/xmake.lua index ef59afe..077ee6e 100644 --- a/vulkanLearn/xmake.lua +++ b/vulkanLearn/xmake.lua @@ -6,6 +6,7 @@ set_project("vulkan") set_toolchains("clang") target("vulkanLearn") set_kind("binary") + add_links("User32") add_defines("VK_USE_PLATFORM_WIN32_KHR") add_packages("vulkansdk","glfw","glm","tinyobjloader") add_includedirs("src/demo", "src/com", "src/external", os.getenv("VULKAN_SDK") .. "/Include/vulkan")