抽象vulkan 基类,梳理代码。

This commit is contained in:
xsl
2025-10-17 15:20:23 +08:00
parent 25fd704a3f
commit a392206f96
4 changed files with 362 additions and 323 deletions
+248
View File
@@ -0,0 +1,248 @@
#include "AppBase.h"
std::vector<char> AppBase::readFile(const std::string& enginePath)
{
std::ifstream file{ enginePath, std::ios::ate | std::ios::binary };
if (!file.is_open())
{
throw std::runtime_error("failed to open file: " + enginePath);
}
size_t fileSize = static_cast<size_t>(file.tellg());
std::vector<char> buffer(fileSize);
file.seekg(0);
file.read(buffer.data(), fileSize);
file.close();
return buffer;
}
VkShaderModule AppBase::createShaderModule(VkDevice& device, const std::vector<char>& code)
{
VkShaderModuleCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = code.size();
createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
VkShaderModule shaderModule;
if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS)
{
throw std::runtime_error("failed to create shader module!");
}
return shaderModule;
}
bool AppBase::checkValidationLayerSupport() {
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
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;
}
void AppBase::createInstance()
{
if (enableValidationLayers && !checkValidationLayerSupport()) {
throw std::runtime_error("validation layers requested, but not available!");
}
VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Sample";
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;
VkInstanceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
std::vector<const char*> extensions;
#ifdef _WIN32
// 获取 GLFW 所需的扩展
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
// 添加调试扩展
for(int i = 0; i < glfwExtensionCount; i++) {
extensions.push_back(glfwExtensions[i]);
}
#endif
if (enableValidationLayers) {
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
createInfo.ppEnabledExtensionNames = extensions.data();
if (enableValidationLayers) {
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
}
else {
createInfo.enabledLayerCount = 0;
}
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
throw std::runtime_error("failed to create instance!");
}
}
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData) {
std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl;
return VK_FALSE;
}
VkResult 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 AppBase::setupDebugMessenger() {
if (!enableValidationLayers)
return;
VkDebugUtilsMessengerCreateInfoEXT createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.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;
createInfo.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;
createInfo.pfnUserCallback = debugCallback;
createInfo.pUserData = nullptr; // Optional
if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
throw std::runtime_error("failed to set up debug messenger!");
}
}
QueueFamilyIndices AppBase::findQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR& surface) {
QueueFamilyIndices indices;
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
int i = 0;
for (const auto& queueFamily : queueFamilies) {
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
indices.graphicsFamily = i;
}
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
if (presentSupport) {
indices.presentFamily = i;
}
if (indices.isComplete()) {
break;
}
i++;
}
return indices;
}
bool AppBase::checkSwapChainSupport(VkPhysicalDevice device, VkSurfaceKHR& surface) {
uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
uint32_t presentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
return formatCount > 0 && presentModeCount > 0;
}
bool AppBase::checkDeviceExtensionSupport(VkPhysicalDevice device) {
// 获取设备支持的扩展数量
uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
// 获取设备支持的扩展列表
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
// 定义需要的扩展
const std::vector<const char*> requiredExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
// 检查所有需要的扩展是否都支持
for (const char* requiredExtension : requiredExtensions) {
bool extensionFound = false;
for (const auto& extension : availableExtensions) {
if (strcmp(requiredExtension, extension.extensionName) == 0) {
extensionFound = true;
break;
}
}
if (!extensionFound) {
return false; // 如果有一个扩展不支持,返回 false
}
}
return true; // 所有扩展都支持
}
bool AppBase::isDeviceSuitable(VkPhysicalDevice device, VkSurfaceKHR& surface) {
QueueFamilyIndices indices = findQueueFamilies(device, surface);
bool extensionsSupported = checkDeviceExtensionSupport(device);
bool swapChainAdequate = false;
if (extensionsSupported) {
swapChainAdequate = checkSwapChainSupport(device, surface);
}
return indices.isComplete() && extensionsSupported && swapChainAdequate;
}
void AppBase::pickPhysicalDevice(VkPhysicalDevice& physicalDevice, VkSurfaceKHR& surface)
{
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
if (deviceCount == 0) {
throw std::runtime_error("failed to find GPUs with Vulkan support!");
}
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
for (const auto& device : devices) {
if (isDeviceSuitable(device, surface)) {
physicalDevice = device;
break;
}
}
if (physicalDevice == VK_NULL_HANDLE) {
throw std::runtime_error("failed to find a suitable GPU!");
}
}
+67
View File
@@ -0,0 +1,67 @@
#ifndef VULKAN_UTILS_H
#define VULKAN_UTILS_H
#define VK_CHECK(x) \
do \
{ \
VkResult err = x; \
if (err) \
{ \
assert(false); \
} \
} while (0)
#ifdef _WIN32
#define logOut std::cout
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#else
#define logOut aout
#include <vulkan/vulkan.h>
#endif
#include <fstream>
#include <iostream>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
#include <vector>
#include <optional>
#include <set>
#include <assert.h>
struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily;
bool isComplete() {
return graphicsFamily.has_value() && presentFamily.has_value();
}
};
class AppBase
{
public:
std::vector<char> readFile(const std::string& enginePath);
VkShaderModule createShaderModule(VkDevice& device, const std::vector<char>& code);
const std::vector<const char*> validationLayers = {"VK_LAYER_KHRONOS_validation"};
protected:
VkInstance instance;
void createInstance();
bool checkValidationLayerSupport();
void setupDebugMessenger();
bool checkSwapChainSupport(VkPhysicalDevice device, VkSurfaceKHR& surface);
bool checkDeviceExtensionSupport(VkPhysicalDevice device);
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR& surface);
bool isDeviceSuitable(VkPhysicalDevice device, VkSurfaceKHR& surface);
void pickPhysicalDevice(VkPhysicalDevice& physicalDevice, VkSurfaceKHR& surface);
#ifdef _WIN32
GLFWwindow *window;
#endif
bool enableValidationLayers = true;
VkDebugUtilsMessengerEXT debugMessenger;
};
#endif // VULKAN_UTILS_H
+39 -232
View File
@@ -9,54 +9,7 @@
#include "../app/src/main/cpp/AndroidOut.h" #include "../app/src/main/cpp/AndroidOut.h"
#endif #endif
bool enableValidationLayers = true;
void Application::createInstance()
{
if (enableValidationLayers && !checkValidationLayerSupport()) {
throw std::runtime_error("validation layers requested, but not available!");
}
VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Sample";
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;
VkInstanceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;
#ifdef _WIN32
// 获取 GLFW 所需的扩展
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
// 添加调试扩展
std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
if (enableValidationLayers) {
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
createInfo.ppEnabledExtensionNames = extensions.data();
#endif
if (enableValidationLayers) {
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
}
else {
createInfo.enabledLayerCount = 0;
}
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
throw std::runtime_error("failed to create instance!");
}
}
void Application::initWindow() void Application::initWindow()
{ {
@@ -66,7 +19,7 @@ void Application::initWindow()
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window = glfwCreateWindow(kWidth, kHeight, "Vulkan", nullptr, nullptr); window = glfwCreateWindow(480, 480, "Vulkan", nullptr, nullptr);
#else #else
#endif #endif
@@ -74,7 +27,6 @@ void Application::initWindow()
void Application::run() void Application::run()
{ {
initWindow();
initVulkan(); initVulkan();
mainLoop(); mainLoop();
cleanup(); cleanup();
@@ -102,49 +54,15 @@ void Application::createSurface() {
#endif #endif
} }
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData) {
std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl;
return VK_FALSE;
}
VkResult 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 Application::setupDebugMessenger() {
if (!enableValidationLayers)
return;
VkDebugUtilsMessengerCreateInfoEXT createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.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;
createInfo.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;
createInfo.pfnUserCallback = debugCallback;
createInfo.pUserData = nullptr; // Optional
if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
throw std::runtime_error("failed to set up debug messenger!");
}
}
void Application::initVulkan() void Application::initVulkan()
{ {
initWindow();
createInstance(); // 创建 Vulkan 实例 createInstance(); // 创建 Vulkan 实例
setupDebugMessenger(); // 在这里调用 setupDebugMessenger(); // 在这里调用
createSurface(); // 创建窗口表面 createSurface(); // 创建窗口表面
pickPhysicalDevice(); // 选择物理设备 pickPhysicalDevice(physicalDevice, surface); // 选择物理设备
createLogicalDevice(); // 创建逻辑设备 createLogicalDevice(); // 创建逻辑设备
createSwapChain(); // 创建交换链 createSwapChain(); // 创建交换链
createImageViews(); // 创建交换链图像视图 createImageViews(); // 创建交换链图像视图
@@ -207,7 +125,7 @@ void Application::createFramebuffers() {
} }
void Application::createCommandPool() { void Application::createCommandPool() {
QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice); QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice, surface);
VkCommandPoolCreateInfo poolInfo{}; VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
@@ -246,109 +164,9 @@ void Application::mainLoop()
} }
void Application::pickPhysicalDevice() {
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
if (deviceCount == 0) {
throw std::runtime_error("failed to find GPUs with Vulkan support!");
}
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
for (const auto& device : devices) {
if (isDeviceSuitable(device)) {
physicalDevice = device;
break;
}
}
if (physicalDevice == VK_NULL_HANDLE) {
throw std::runtime_error("failed to find a suitable GPU!");
}
}
QueueFamilyIndices Application::findQueueFamilies(VkPhysicalDevice device) {
QueueFamilyIndices indices;
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
int i = 0;
for (const auto& queueFamily : queueFamilies) {
if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
indices.graphicsFamily = i;
}
VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
if (presentSupport) {
indices.presentFamily = i;
}
if (indices.isComplete()) {
break;
}
i++;
}
return indices;
}
bool Application::checkDeviceExtensionSupport(VkPhysicalDevice device) {
// 获取设备支持的扩展数量
uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
// 获取设备支持的扩展列表
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
// 定义需要的扩展
const std::vector<const char*> requiredExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
// 检查所有需要的扩展是否都支持
for (const char* requiredExtension : requiredExtensions) {
bool extensionFound = false;
for (const auto& extension : availableExtensions) {
if (strcmp(requiredExtension, extension.extensionName) == 0) {
extensionFound = true;
break;
}
}
if (!extensionFound) {
return false; // 如果有一个扩展不支持,返回 false
}
}
return true; // 所有扩展都支持
}
bool Application::checkSwapChainSupport(VkPhysicalDevice device) {
uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
uint32_t presentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
return formatCount > 0 && presentModeCount > 0;
}
bool Application::isDeviceSuitable(VkPhysicalDevice device) {
QueueFamilyIndices indices = findQueueFamilies(device);
bool extensionsSupported = checkDeviceExtensionSupport(device);
bool swapChainAdequate = false;
if (extensionsSupported) {
swapChainAdequate = checkSwapChainSupport(device);
}
return indices.isComplete() && extensionsSupported && swapChainAdequate;
}
void Application::createLogicalDevice() { void Application::createLogicalDevice() {
QueueFamilyIndices indices = findQueueFamilies(physicalDevice); QueueFamilyIndices indices = findQueueFamilies(physicalDevice, surface);
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos; std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() }; std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() };
@@ -386,26 +204,31 @@ void Application::createLogicalDevice() {
vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue); vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue);
} }
//vk::Extent2D choose_extent(vk::Extent2D request_extent, inline VkExtent2D choose_extent(
// const vk::Extent2D& min_image_extent, VkExtent2D request_extent,
// const vk::Extent2D& max_image_extent, const VkExtent2D &min_image_extent,
// const vk::Extent2D& current_extent) const VkExtent2D &max_image_extent,
//{ const VkExtent2D &current_extent)
// if (current_extent.width == 0xFFFFFFFF) {
// { if (current_extent.width == 0xFFFFFFFF)
// return request_extent; {
// } return request_extent;
// }
// if (request_extent.width < 1 || request_extent.height < 1)
// { if (request_extent.width < 1 || request_extent.height < 1)
// return current_extent; {
// } logOut << "(Swapchain) Image extent ("<< request_extent.width << ", " << request_extent.height << ") not supported. Selecting ("<< current_extent.width << ", " << current_extent.height << ")." << std::endl;
// return current_extent;
// request_extent.width = clamp(request_extent.width, min_image_extent.width, max_image_extent.width); }
// request_extent.height = clamp(request_extent.height, min_image_extent.height, max_image_extent.height);
// request_extent.width = std::max(request_extent.width, min_image_extent.width);
// return request_extent; request_extent.width = std::min(request_extent.width, max_image_extent.width);
//}
request_extent.height = std::max(request_extent.height, min_image_extent.height);
request_extent.height = std::min(request_extent.height, max_image_extent.height);
return request_extent;
}
void Application::createSwapChain() { void Application::createSwapChain() {
// 选择交换链格式、颜色空间和分辨率 // 选择交换链格式、颜色空间和分辨率
@@ -413,6 +236,10 @@ void Application::createSwapChain() {
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
VkExtent2D extent = { 0, 0 }; VkExtent2D extent = { 0, 0 };
VkSurfaceCapabilitiesKHR surface_capabilities{};
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(this->physicalDevice, this->surface, &surface_capabilities);
extent = choose_extent(extent, surface_capabilities.minImageExtent, surface_capabilities.maxImageExtent, surface_capabilities.currentExtent);
// 创建交换链 // 创建交换链
VkSwapchainCreateInfoKHR createInfo{}; VkSwapchainCreateInfoKHR createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
@@ -420,11 +247,11 @@ void Application::createSwapChain() {
createInfo.minImageCount = 2; // 双缓冲 createInfo.minImageCount = 2; // 双缓冲
createInfo.imageFormat = surfaceFormat.format; createInfo.imageFormat = surfaceFormat.format;
createInfo.imageColorSpace = surfaceFormat.colorSpace; createInfo.imageColorSpace = surfaceFormat.colorSpace;
//createInfo.imageExtent = choose_extent(extent, surface_capabilities.minImageExtent, surface_capabilities.maxImageExtent, surface_capabilities.currentExtent);; createInfo.imageExtent = extent;
createInfo.imageArrayLayers = 1; createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
QueueFamilyIndices indices = findQueueFamilies(physicalDevice); QueueFamilyIndices indices = findQueueFamilies(physicalDevice, surface);
uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() }; uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() };
if (indices.graphicsFamily != indices.presentFamily) { if (indices.graphicsFamily != indices.presentFamily) {
@@ -477,8 +304,8 @@ void Application::createGraphicsPipeline() {
auto fragShaderCode = readFile("shaders/simple_shader.frag.spv"); auto fragShaderCode = readFile("shaders/simple_shader.frag.spv");
// 创建着色器模块 // 创建着色器模块
VkShaderModule vertShaderModule = createShaderModule(vertShaderCode); VkShaderModule vertShaderModule = createShaderModule(this->device, vertShaderCode);
VkShaderModule fragShaderModule = createShaderModule(fragShaderCode); VkShaderModule fragShaderModule = createShaderModule(this->device, fragShaderCode);
// 定义着色器阶段 // 定义着色器阶段
VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; VkPipelineShaderStageCreateInfo vertShaderStageInfo{};
@@ -613,27 +440,7 @@ void Application::createRenderPass() {
} }
} }
bool Application::checkValidationLayerSupport() {
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
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;
}
void Application::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) { void Application::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) {
VkCommandBufferBeginInfo beginInfo{}; VkCommandBufferBeginInfo beginInfo{};
+8 -91
View File
@@ -1,106 +1,28 @@
#pragma once #pragma once
#ifdef _WIN32
#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>
#else
#include <vulkan/vulkan.h>
#endif
#include <fstream> #include "AppBase.h"
#include <iostream>
#include <iostream>
#include <stdexcept>
#include <cstdlib>
#include <vector>
#include <optional>
#include <set>
#include <assert.h>
#include <vulkan/vulkan_structs.hpp>
#define VK_CHECK(x) \
do \
{ \
VkResult err = x; \
if (err) \
{ \
assert(false); \
} \
} while (0)
struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily;
bool isComplete() {
return graphicsFamily.has_value() && presentFamily.has_value();
}
};
class Application
class Application : public AppBase
{ {
private:
std::vector<char> readFile(const std::string &enginePath)
{
std::ifstream file{enginePath, std::ios::ate | std::ios::binary};
if (!file.is_open())
{
throw std::runtime_error("failed to open file: " + enginePath);
}
size_t fileSize = static_cast<size_t>(file.tellg());
std::vector<char> buffer(fileSize);
file.seekg(0);
file.read(buffer.data(), fileSize);
file.close();
return buffer;
}
VkShaderModule createShaderModule(const std::vector<char> &code)
{
VkShaderModuleCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = code.size();
createInfo.pCode = reinterpret_cast<const uint32_t *>(code.data());
VkShaderModule shaderModule;
if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS)
{
throw std::runtime_error("failed to create shader module!");
}
return shaderModule;
}
public: public:
void run(); void run();
private: protected:
#ifdef _WIN32 void initVulkan();
GLFWwindow *window;
#endif
VkInstance instance;
void initWindow(); void initWindow();
void createSurface(); void createSurface();
void initVulkan();
void mainLoop(); void mainLoop();
void cleanup(); void cleanup();
void createInstance();
void createImageViews(); void createImageViews();
void createFramebuffers(); void createFramebuffers();
void createCommandPool(); void createCommandPool();
void createCommandBuffer(); void createCommandBuffer();
void setupDebugMessenger();
void pickPhysicalDevice();
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device);
bool isDeviceSuitable(VkPhysicalDevice device);
bool checkSwapChainSupport(VkPhysicalDevice device);
bool checkDeviceExtensionSupport(VkPhysicalDevice device);
bool checkValidationLayerSupport();
void createLogicalDevice(); void createLogicalDevice();
void createSwapChain(); void createSwapChain();
void createPipelineLayout(); void createPipelineLayout();
@@ -129,10 +51,5 @@ private:
VkSemaphore renderFinishedSemaphore; // 渲染完成信号量 VkSemaphore renderFinishedSemaphore; // 渲染完成信号量
VkFence inFlightFence; // 同步栅栏 VkFence inFlightFence; // 同步栅栏
VkQueue presentQueue; // 呈现队列 VkQueue presentQueue; // 呈现队列
VkDebugUtilsMessengerEXT debugMessenger;
const std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};
const uint32_t kWidth = 480;
const uint32_t kHeight = 480;
}; };