From 7063d9a0f9ca022bd2b5a08cd8756428ebeb8ea1 Mon Sep 17 00:00:00 2001 From: ink-soul Date: Tue, 2 Apr 2024 12:08:46 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=AE=8C=E6=88=90=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E8=AE=BE=E5=A4=87=E5=88=9B=E5=BB=BA=EF=BC=8Csurface?= =?UTF-8?q?=E5=88=9B=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/vulkanexamplebase.cpp | 12 +-- src/render/render.cpp | 18 +++- src/render/render.h | 6 +- src/render/vulkanFoundation.cpp | 165 ++++++++++++++++++++++++++++++-- src/render/vulkanFoundation.h | 51 +++++++--- 5 files changed, 223 insertions(+), 29 deletions(-) diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 2cb55db..1fc9c9e 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -9,8 +9,8 @@ #include "VulkanExampleBase.h" -std::vector VulkanExampleBase::args; +/* VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char * pLayerPrefix, const char * pMsg, void * pUserData) { std::string prefix(""); @@ -33,7 +33,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback(VkDebugReportFlagsEXT flags, fflush(stdout); return VK_FALSE; } - +*/ VkResult VulkanExampleBase::createInstance(bool enableValidation) { setter.settings.validation = enableValidation; @@ -591,7 +591,7 @@ void VulkanExampleBase::initVulkan() /* Validation layers - */ + if (settings.validation) { vkCreateDebugReportCallback = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT")); vkDestroyDebugReportCallback = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT")); @@ -601,10 +601,10 @@ void VulkanExampleBase::initVulkan() debugCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; VK_CHECK_RESULT(vkCreateDebugReportCallback(instance, &debugCreateInfo, nullptr, &debugReportCallback)); } - + */ /* GPU selection - */ + uint32_t gpuCount = 0; VK_CHECK_RESULT(vkEnumeratePhysicalDevices(instance, &gpuCount, nullptr)); assert(gpuCount > 0); @@ -620,7 +620,7 @@ void VulkanExampleBase::initVulkan() vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties); vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures); vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties); - + */ /* Device creation */ diff --git a/src/render/render.cpp b/src/render/render.cpp index 8b7b7d7..ced2dee 100644 --- a/src/render/render.cpp +++ b/src/render/render.cpp @@ -2269,10 +2269,12 @@ void PlumageRender::updateUIOverlay() } + // 完全重写,避免OS specific +/* PlumageRender* plumageRender; -// OS specific macros for the example main entry points + #if defined(_WIN32) LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -2299,3 +2301,17 @@ PlumageRender* plumageRender; return 0; } #endif +*/ + +int main() +{ + PlumageRender* plumageRender; + VulkanBackend::Setter setter; + if (!setter.settings.headless) + { + plumageRender->initWindow(setter.settings.width, setter.settings.height); + plumageRender->initVulkan(); + } + return 0; +} + diff --git a/src/render/render.h b/src/render/render.h index ab7deb2..506c8a6 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -19,12 +19,15 @@ #include #include "VulkanExampleBase.h" #include "glTFModel.h" +#include "GLFW/glfw3.h" #include #include "VulkanDevice.hpp" #include "ui.hpp" #include #include "renderSetter.h" -#include "GLFW/glfw3.h" +#include "vulkanFoundation.h" + + #define STB_IMAGE_WRITE_IMPLEMENTATION #include "stb_image_write.h" @@ -296,6 +299,7 @@ public: void initWindow(int width, int height); + static void framebufferResizeCallback(GLFWwindow* window, int width, int height); void renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFModel::Material::AlphaMode alphaMode); void loadScene(std::string filename); diff --git a/src/render/vulkanFoundation.cpp b/src/render/vulkanFoundation.cpp index d511783..65c45ff 100644 --- a/src/render/vulkanFoundation.cpp +++ b/src/render/vulkanFoundation.cpp @@ -1,12 +1,27 @@ #include "vulkanFoundation.h" -VKAPI_ATTR VkBool32 VKAPI_CALL VulkanBackend::VulkanFondation::debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) -{ - std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl; - return VK_FALSE; +void VulkanBackend::VulkanFondation::initVulkan() +{ + // 创建instance + createInstance(); + + // 设置校验层消息回调 + setupDebugMessager(); + + // 选择主机显卡 + pickPhysicalDevice(); + + // 实时显示结果的glfw surface + createSurface(); + + // 完成逻辑设备创建 + createLogicalDevice(); + } + + void VulkanBackend::VulkanFondation::createInstance() { // check validation layers @@ -106,6 +121,25 @@ std::vector VulkanBackend::VulkanFondation::getRequiredExtensions() return extensions; } + + +void VulkanBackend::VulkanFondation::setupDebugMessager() +{ + if (!setter.settings.validation) + { + return; + } + + VkDebugUtilsMessengerCreateInfoEXT createInfo{}; + populateDebugMessengerCreateInfo(createInfo); + + + if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) + { + throw std::runtime_error("failed to set up debug messenger in setupDebugMessenger"); + } +} + void VulkanBackend::VulkanFondation::populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& debugCreateInfo) { debugCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; @@ -119,13 +153,49 @@ void VulkanBackend::VulkanFondation::populateDebugMessengerCreateInfo(VkDebugUti debugCreateInfo.pfnUserCallback = &debugCallback; debugCreateInfo.pUserData = nullptr; } +// debugCallback用于校验层 +VKAPI_ATTR VkBool32 VKAPI_CALL VulkanBackend::VulkanFondation::debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) +{ + { + std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl; + + return VK_FALSE; + } +} + +VkResult VulkanBackend::VulkanFondation::CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) +{ + auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); + + if (func != nullptr) + { + return func(instance, pCreateInfo, pAllocator, pDebugMessenger); + } + else + { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } +} + + void VulkanBackend::VulkanFondation::createSurface() { + if (setter.settings.headless) + { + return; + } + + if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) + { + throw std::runtime_error("failed to create window surface in createSurface()"); + } } -inline void VulkanBackend::VulkanFondation::pickPhysicalDevice() + + +void VulkanBackend::VulkanFondation::pickPhysicalDevice() { uint32_t deviceCount = 0; @@ -208,12 +278,13 @@ VulkanBackend::VulkanFondation::QueueFamilyIndices VulkanBackend::VulkanFondatio VkBool32 presentSupport = false; - // 检查队列支持 + // 检查显示队列支持 int i = 0; if (!setter.settings.headless) { vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); } + for (const auto& queueFamily : queueFamilies) { if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { @@ -238,9 +309,7 @@ VulkanBackend::VulkanFondation::QueueFamilyIndices VulkanBackend::VulkanFondatio { indices.presentFamily = i; } - i++; - } return indices; @@ -273,3 +342,83 @@ VulkanBackend::VulkanFondation::SwapChainSupportDetails VulkanBackend::VulkanFon return details; } + + + +void VulkanBackend::VulkanFondation::createLogicalDevice() +{ + QueueFamilyIndices indices = findQueueFamilies(physicalDevice); + std::vector queueCreateInfos; + + if (setter.settings.headless) + { + VkDeviceQueueCreateInfo queueCreateInfo{}; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value(); + queueCreateInfo.queueCount = 1; + float queuePriority = 1.0f; + queueCreateInfo.pQueuePriorities = &queuePriority; + queueCreateInfos.push_back(queueCreateInfo); + } + else + { + + std::set uniqueQueueFamilies = { indices.graphicsFamily.value(),indices.presentFamily.value() }; + + float queuePriority = 1.0f; + for (uint32_t 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); + } + } + + VkPhysicalDeviceFeatures enableFeatures{}; + if (deviceFeatures.samplerAnisotropy) { + enableFeatures.samplerAnisotropy = VK_TRUE; + } + + std::vector enabledExtensions{}; + if (!setter.settings.headless) + { + for (auto swapchainExtension: swapchainExtensions) + { + enabledExtensions.push_back(swapchainExtension); + } + } + + VkDeviceCreateInfo deviceCreateInfo{}; + deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + deviceCreateInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); + deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data(); + deviceCreateInfo.pEnabledFeatures = &enableFeatures; + deviceCreateInfo.enabledExtensionCount = static_cast(enabledExtensions.size()); + deviceCreateInfo.ppEnabledExtensionNames = enabledExtensions.data(); + + //新版本vulkan已不对实例和设备特定验证层做区分,此处保证兼容性 + if (setter.settings.validation) + { + deviceCreateInfo.enabledLayerCount = static_cast(validationLayers.size()); + deviceCreateInfo.ppEnabledLayerNames = validationLayers.data(); + } + else + { + deviceCreateInfo.enabledLayerCount = 0; + } + + if (vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device) != VK_SUCCESS) + { + throw std::runtime_error("failed to create logical device"); + } + + vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicQueue); + if (setter.settings.headless) + { + vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue); + } + +} diff --git a/src/render/vulkanFoundation.h b/src/render/vulkanFoundation.h index b68d0b5..aa00f73 100644 --- a/src/render/vulkanFoundation.h +++ b/src/render/vulkanFoundation.h @@ -27,24 +27,24 @@ namespace VulkanBackend //"VK_EXT_headless_surface" }; - VulkanBackend::Setter setter; - - + const int MAX_FRAME_IN_FLIGHT = 2; + void initVulkan(); + + private: + VulkanBackend::Setter setter; VkInstance instance; + VkDebugUtilsMessengerEXT debugMessenger; - VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; - VkDevice device; - VkSurfaceKHR surface; struct QueueFamilyIndices { std::optional graphicsFamily; std::optional presentFamily; - bool isGraphicsFamilyComplete() + bool isGraphicsFamilyComplete() { return graphicsFamily.has_value(); } @@ -61,23 +61,48 @@ namespace VulkanBackend std::vector presentModes; }; + VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; + VkDevice device; + + GLFWwindow* window; + VkSurfaceKHR surface; + + VkPhysicalDeviceFeatures deviceFeatures; + VkQueue graphicQueue; + VkQueue presentQueue; + + + + + // 句柄创建,检查校验层支持和获取需要的扩展 + void createInstance(); + bool checkValidationLayerSupport(); + std::vector getRequiredExtensions(); + + // 实时显示结果使用的glfwSurface,受headless配置项控制 + void createSurface(); + + // 设置校验层使用的消息回调 + void setupDebugMessager(); + void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& debugCreateInfo); static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData); - - void createInstance(); - bool checkValidationLayerSupport(); - std::vector getRequiredExtensions(); - void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& debugCreateInfo); + VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger); - void createSurface(); + // 通过检查队列、交换链、扩展支持,选择合适的显卡 void pickPhysicalDevice(); bool isDeviceSuitable(VkPhysicalDevice device); bool checkDeviceExtensionSupport(VkPhysicalDevice device); VulkanBackend::VulkanFondation::QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device); VulkanBackend::VulkanFondation::SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device); + + // 创建程序使用的逻辑显卡设备 + + void createLogicalDevice(); + }; VulkanFondation::VulkanFondation()