From 77e93d01d142137f5474e2d8b1254d0494d54098 Mon Sep 17 00:00:00 2001 From: ink-soul Date: Mon, 1 Apr 2024 18:05:17 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E8=87=B3debugCallBack?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/vulkanexamplebase.cpp | 1 + src/render/render.cpp | 73 +++++++------ src/render/render.h | 12 +-- src/render/vulkanFoundation.cpp | 185 ++++++++++++++++++++++++++++++-- src/render/vulkanFoundation.h | 41 +++++-- 5 files changed, 256 insertions(+), 56 deletions(-) diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 1f138f8..2cb55db 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -1801,6 +1801,7 @@ void VulkanExampleBase::setupFrameBuffer() imageCI.samples = settings.sampleCount; imageCI.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VK_CHECK_RESULT(vkCreateImage(device, &imageCI, nullptr, &multisampleTarget.color.image)); VkMemoryRequirements memReqs; diff --git a/src/render/render.cpp b/src/render/render.cpp index 7441c48..8b7b7d7 100644 --- a/src/render/render.cpp +++ b/src/render/render.cpp @@ -43,6 +43,8 @@ void PlumageRender::framebufferResizeCallback(GLFWwindow* window, int width, int app->framebufferResized = true; } + +// 重构至gltfModel中 void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFModel::Material::AlphaMode alphaMode) { if (node->mesh) { // Render mesh primitives @@ -121,7 +123,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode } } - void PlumageRender::buildCommandBuffers() +void PlumageRender::buildCommandBuffers() { VkCommandBufferBeginInfo cmdBufferBeginInfo{}; cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -213,7 +215,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode } - void PlumageRender::loadScene(std::string filename) +void PlumageRender::loadScene(std::string filename) { std::cout << "Loading scene from " << filename << std::endl; models.scene.destroy(device); @@ -227,7 +229,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode camera.setRotation({ 0.0f, 0.0f, 0.0f }); } - void PlumageRender::loadEnvironment(std::string filename) +void PlumageRender::loadEnvironment(std::string filename) { std::cout << "Loading environment from " << filename << std::endl; if (textures.environmentCube.image) { @@ -239,7 +241,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode generateCubemaps(); } - void PlumageRender::loadAssets() +void PlumageRender::loadAssets() { const std::string assetpath = getAssetPath(); @@ -268,7 +270,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode loadEnvironment(envMapFile.c_str()); } - void PlumageRender::setupNodeDescriptorSet(glTFModel::Node* node) +void PlumageRender::setupNodeDescriptorSet(glTFModel::Node* node) { /* This sample uses separate descriptor sets (and layouts) for the matrices and materials (textures) @@ -296,7 +298,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode } } - void PlumageRender::setupDescriptors() +void PlumageRender::setupDescriptors() { /* Descriptor Pool @@ -519,7 +521,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode } } - void PlumageRender::preparePipelines() +void PlumageRender::preparePipelines() { VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI{}; inputAssemblyStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; @@ -667,10 +669,11 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode } - // generate two cube maps - // irradiance cube map - // prefileter environment cube map - void PlumageRender::generateCubemaps() +// generate two cube maps +// irradiance cube map +// prefileter environment cube map +// 重构到PBR中 +void PlumageRender::generateCubemaps() { enum Target { IRRADIANCE = 0, PREFILTEREDENV = 1 }; @@ -1207,8 +1210,9 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode std::cout << "Generating cube map with " << numMips << " mip levels took " << tDiff << " ms" << std::endl; } } - // generate BRDF integration map for roughness/NdotV - void PlumageRender::generateBRDFLUT() +// generate BRDF integration map for roughness/NdotV +// 重构到PBR +void PlumageRender::generateBRDFLUT() { auto tStart = std::chrono::high_resolution_clock::now(); @@ -1465,8 +1469,8 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode std::cout << "Generating BRDF LUT took " << tDiff << " ms" << std::endl; } - // Prepare and initialize uniform buffer containing shader uniforms - void PlumageRender::prepareUniformBuffers() +// Prepare and initialize uniform buffer containing shader uniforms +void PlumageRender::prepareUniformBuffers() { for (auto& uniformBuffer : uniformBuffers) { uniformBuffer.scene.create(vulkanDevice, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, sizeof(shaderDataScene)); @@ -1475,8 +1479,8 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode } updateUniformBuffers(); } - - void PlumageRender::updateUniformBuffers() +// 更新统一缓冲区 +void PlumageRender::updateUniformBuffers() { // Scene shaderDataScene.projection = camera.matrices.perspective; @@ -1505,7 +1509,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode shaderDataSkybox.model = glm::mat4(glm::mat3(camera.matrices.view)); } - void PlumageRender::updateShaderData() +void PlumageRender::updateShaderData() { shaderData.lightDir = glm::vec4( sin(glm::radians(lightSource.rotation.x)) * cos(glm::radians(lightSource.rotation.y)), @@ -1513,8 +1517,8 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode cos(glm::radians(lightSource.rotation.x)) * cos(glm::radians(lightSource.rotation.y)), 0.0f); } - - void PlumageRender::windowResized() +// todo:重写成glfw的 +void PlumageRender::windowResized() { buildCommandBuffers(); vkDeviceWaitIdle(device); @@ -1523,7 +1527,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode updateUIOverlay(); } - void PlumageRender::prepare() +void PlumageRender::prepare() { VulkanExampleBase::prepare(); @@ -1587,7 +1591,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode prepared = true; } - void PlumageRender::submitWork(VkCommandBuffer cmdBuffer, VkQueue queue) +void PlumageRender::submitWork(VkCommandBuffer cmdBuffer, VkQueue queue) { VkSubmitInfo submitInfo = vks::initializers::submitInfo(); submitInfo.commandBufferCount = 1; @@ -1600,8 +1604,9 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode vkDestroyFence(device, fence, nullptr); } - // todo :根据physicalDeviceIndex确定子文件夹路径,frameIndex确定fileName - void PlumageRender::writeImageToFile(std::string filePath) +// todo :根据physicalDeviceIndex确定子文件夹路径,frameIndex确定fileName +// 移动到fileSystem里 +void PlumageRender::writeImageToFile(std::string filePath) { bool screenshotSaved = false; @@ -1834,7 +1839,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode } - void PlumageRender::outputImageSequence() +void PlumageRender::outputImageSequence() { // 比较已保存的帧数和设置里的开始帧数,在生成前清理上一次生成的图片序列 if (savedFrameCounter == setter.settings.startFrameCount) @@ -1874,7 +1879,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode savedFrameCounter++; } - void PlumageRender::imageSequenceToVideo() +void PlumageRender::imageSequenceToVideo() { // 边界条件,图片序列输出未完成 if (!signal.imageSequenceOutputComplete) @@ -1914,7 +1919,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode removeImageSequence(); } - void PlumageRender::removeImageSequence() +void PlumageRender::removeImageSequence() { // 函数非第一次运行的边界条件 if (savedFrameCounter != setter.settings.startFrameCount) @@ -1949,7 +1954,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode - void PlumageRender::render() +void PlumageRender::render() { if (!prepared) { return; @@ -2042,7 +2047,7 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode } - void PlumageRender::fileDropped(std::string filename) +void PlumageRender::fileDropped(std::string filename) { vkDeviceWaitIdle(device); loadScene(filename); @@ -2050,8 +2055,8 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode buildCommandBuffers(); } - - void PlumageRender::updateUIOverlay() +// 重构到单独的UI里 +void PlumageRender::updateUIOverlay() { ImGuiIO& io = ImGui::GetIO(); @@ -2265,9 +2270,9 @@ void PlumageRender::renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFMode } - - PlumageRender* plumageRender; - // OS specific macros for the example main entry points +// 完全重写,避免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) { diff --git a/src/render/render.h b/src/render/render.h index 0125fb5..ab7deb2 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -300,19 +300,19 @@ public: void renderNode(glTFModel::Node* node, uint32_t cbIndex, glTFModel::Material::AlphaMode alphaMode); void loadScene(std::string filename); void loadEnvironment(std::string filename); - void buildCommandBuffers(); - void loadAssets(); + void buildCommandBuffers(); + void loadAssets(); void setupNodeDescriptorSet(glTFModel::Node* node); void setupDescriptors(); - void preparePipelines(); + void preparePipelines(); // void tonemappingPipelin(); void generateCubemaps(); void generateBRDFLUT(); - void prepareUniformBuffers(); - void updateUniformBuffers(); + void prepareUniformBuffers(); + void updateUniformBuffers(); void updateShaderData(); void windowResized(); - void prepare(); + void prepare(); void submitWork(VkCommandBuffer cmdBuffer, VkQueue queue); void writeImageToFile(std::string filePath); diff --git a/src/render/vulkanFoundation.cpp b/src/render/vulkanFoundation.cpp index 3eef5bb..d511783 100644 --- a/src/render/vulkanFoundation.cpp +++ b/src/render/vulkanFoundation.cpp @@ -1,5 +1,125 @@ #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::createInstance() +{ + // check validation layers + if (setter.settings.validation && !checkValidationLayerSupport()) + { + throw std::runtime_error("validation layers requsted,but not available"); + } + + //setup appliaction info + VkApplicationInfo appInfo{}; + + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = "Hello Triangle"; + appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.pEngineName = "No_Engine"; + appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.apiVersion = VK_API_VERSION_1_0; + + // setup createInfo + VkInstanceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &appInfo; + + auto requiredExtensions = getRequiredExtensions(); + createInfo.enabledExtensionCount = static_cast(requiredExtensions.size()); + createInfo.ppEnabledExtensionNames = requiredExtensions.data(); + + + // enable validation layer if available in createInfo + VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; + if (setter.settings.validation) + { + createInfo.enabledLayerCount = static_cast(validationLayers.size()); + createInfo.ppEnabledLayerNames = validationLayers.data(); + + populateDebugMessengerCreateInfo(debugCreateInfo); + createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo; + } + else + { + createInfo.enabledLayerCount = 0; + createInfo.pNext = nullptr; + } + + // throw error in creating instance + if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) + { + throw std::runtime_error("failed to create instance"); + } +} + +bool VulkanBackend::VulkanFondation::checkValidationLayerSupport() +{ + uint32_t layerCount; + vkEnumerateInstanceLayerProperties(&layerCount, nullptr); + + std::vector availableLayers(layerCount); + vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); + + // check if validationLayers can be found in availableLayers + for (const char* layerName : validationLayers) + { + bool layerFound = false; + for (const auto& layerProperties : availableLayers) { + if (strcmp(layerName, layerProperties.layerName) == 0) + { + layerFound = true; + break; + } + } + if (!layerFound) + { + return false; + } + } + return true; +} + +std::vector VulkanBackend::VulkanFondation::getRequiredExtensions() +{ + std::vector extensions; + if (!setter.settings.headless) + { + uint32_t glfwExtensionCount = 0; + const char** glfwExtensions; + glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + + std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); + } + + if (setter.settings.validation) + { + extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + + } + + return extensions; +} + +void VulkanBackend::VulkanFondation::populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& debugCreateInfo) +{ + debugCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + + debugCreateInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + debugCreateInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + debugCreateInfo.pfnUserCallback = &debugCallback; + debugCreateInfo.pUserData = nullptr; +} + void VulkanBackend::VulkanFondation::createSurface() { @@ -45,7 +165,7 @@ bool VulkanBackend::VulkanFondation::isDeviceSuitable(VkPhysicalDevice device) return extensionsSupported; } else - { + { // 非无头下在检查扩展支持的同时要检查swapchain bool extensionsSupported = checkDeviceExtensionSupport(device); bool swapChainAdequate = false; QueueFamilyIndices indices = findQueueFamilies(device); @@ -59,7 +179,21 @@ bool VulkanBackend::VulkanFondation::isDeviceSuitable(VkPhysicalDevice device) bool VulkanBackend::VulkanFondation::checkDeviceExtensionSupport(VkPhysicalDevice device) { - return false; + uint32_t extensionCount; + vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); + + std::vector availableExtensions(extensionCount); + vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data()); + + std::set requiredExtensions(swapchainExtensions.begin(), swapchainExtensions.end()); + + for (const auto& extension : availableExtensions) + { + requiredExtensions.erase(extension.extensionName); + } + + return requiredExtensions.empty(); + } VulkanBackend::VulkanFondation::QueueFamilyIndices VulkanBackend::VulkanFondation::findQueueFamilies(VkPhysicalDevice device) @@ -74,17 +208,31 @@ VulkanBackend::VulkanFondation::QueueFamilyIndices VulkanBackend::VulkanFondatio VkBool32 presentSupport = false; - + // 检查队列支持 int i = 0; - vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); + if (!setter.settings.headless) + { + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); + } for (const auto& queueFamily : queueFamilies) { if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { indices.graphicsFamily = i; } - if (indices.isComplete()) + // 无头下不需要检查present queue + if (setter.settings.headless) { - break; + if (indices.isGraphicsFamilyComplete()) + { + break; + } + } + else + { + if (indices.isGraphicsFamilyComplete() && indices.isPresentFamilyComplete()) + { + break; + } } if (presentSupport) { @@ -100,5 +248,28 @@ VulkanBackend::VulkanFondation::QueueFamilyIndices VulkanBackend::VulkanFondatio VulkanBackend::VulkanFondation::SwapChainSupportDetails VulkanBackend::VulkanFondation::querySwapChainSupport(VkPhysicalDevice device) { - + // 获得surface细节 + SwapChainSupportDetails details; + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities); + + // 检查格式支持(image) + uint32_t formatCount; + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr); + if (formatCount != 0) + { + details.formats.resize(formatCount); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data()); + } + + // 检查显示模式支持 + uint32_t presentModeCount; + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr); + + if (presentModeCount != 0) + { + details.presentModes.resize(presentModeCount); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data()); + } + + return details; } diff --git a/src/render/vulkanFoundation.h b/src/render/vulkanFoundation.h index c710aa3..b68d0b5 100644 --- a/src/render/vulkanFoundation.h +++ b/src/render/vulkanFoundation.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "renderSetter.h" @@ -16,13 +17,25 @@ namespace VulkanBackend VulkanFondation(); ~VulkanFondation(); + const std::vector validationLayers = { + "VK_LAYER_KHRONOS_validation" + + }; + + const std::vector swapchainExtensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + //"VK_EXT_headless_surface" + }; + VulkanBackend::Setter setter; - VkInstance instance; private: + VkInstance instance; + VkDebugUtilsMessengerEXT debugMessenger; + VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; VkDevice device; VkSurfaceKHR surface; @@ -31,8 +44,13 @@ namespace VulkanBackend std::optional graphicsFamily; std::optional presentFamily; - bool isComplete() { - return graphicsFamily.has_value() && presentFamily.has_value(); + bool isGraphicsFamilyComplete() + { + return graphicsFamily.has_value(); + } + bool isPresentFamilyComplete() + { + return presentFamily.has_value(); } }; @@ -43,14 +61,19 @@ namespace VulkanBackend std::vector presentModes; }; + 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); - - void pickPhysicalDevice(); - - - void createSurface(); - + void pickPhysicalDevice(); bool isDeviceSuitable(VkPhysicalDevice device); bool checkDeviceExtensionSupport(VkPhysicalDevice device); VulkanBackend::VulkanFondation::QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device);