抽象vulkan 基类,梳理代码。
This commit is contained in:
@@ -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!");
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -9,54 +9,7 @@
|
||||
#include "../app/src/main/cpp/AndroidOut.h"
|
||||
#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()
|
||||
{
|
||||
@@ -66,7 +19,7 @@ void Application::initWindow()
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
|
||||
window = glfwCreateWindow(kWidth, kHeight, "Vulkan", nullptr, nullptr);
|
||||
window = glfwCreateWindow(480, 480, "Vulkan", nullptr, nullptr);
|
||||
#else
|
||||
|
||||
#endif
|
||||
@@ -74,7 +27,6 @@ void Application::initWindow()
|
||||
|
||||
void Application::run()
|
||||
{
|
||||
initWindow();
|
||||
initVulkan();
|
||||
mainLoop();
|
||||
cleanup();
|
||||
@@ -102,49 +54,15 @@ void Application::createSurface() {
|
||||
#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()
|
||||
{
|
||||
initWindow();
|
||||
createInstance(); // 创建 Vulkan 实例
|
||||
setupDebugMessenger(); // 在这里调用
|
||||
setupDebugMessenger(); // 在这里调用
|
||||
createSurface(); // 创建窗口表面
|
||||
pickPhysicalDevice(); // 选择物理设备
|
||||
pickPhysicalDevice(physicalDevice, surface); // 选择物理设备
|
||||
createLogicalDevice(); // 创建逻辑设备
|
||||
createSwapChain(); // 创建交换链
|
||||
createImageViews(); // 创建交换链图像视图
|
||||
@@ -207,7 +125,7 @@ void Application::createFramebuffers() {
|
||||
}
|
||||
|
||||
void Application::createCommandPool() {
|
||||
QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice);
|
||||
QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice, surface);
|
||||
|
||||
VkCommandPoolCreateInfo poolInfo{};
|
||||
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() {
|
||||
QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
|
||||
QueueFamilyIndices indices = findQueueFamilies(physicalDevice, surface);
|
||||
|
||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
||||
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);
|
||||
}
|
||||
|
||||
//vk::Extent2D choose_extent(vk::Extent2D request_extent,
|
||||
// const vk::Extent2D& min_image_extent,
|
||||
// const vk::Extent2D& max_image_extent,
|
||||
// const vk::Extent2D& current_extent)
|
||||
//{
|
||||
// if (current_extent.width == 0xFFFFFFFF)
|
||||
// {
|
||||
// return request_extent;
|
||||
// }
|
||||
//
|
||||
// if (request_extent.width < 1 || request_extent.height < 1)
|
||||
// {
|
||||
// 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);
|
||||
//
|
||||
// return request_extent;
|
||||
//}
|
||||
inline VkExtent2D choose_extent(
|
||||
VkExtent2D request_extent,
|
||||
const VkExtent2D &min_image_extent,
|
||||
const VkExtent2D &max_image_extent,
|
||||
const VkExtent2D ¤t_extent)
|
||||
{
|
||||
if (current_extent.width == 0xFFFFFFFF)
|
||||
{
|
||||
return request_extent;
|
||||
}
|
||||
|
||||
if (request_extent.width < 1 || request_extent.height < 1)
|
||||
{
|
||||
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 = std::max(request_extent.width, min_image_extent.width);
|
||||
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() {
|
||||
// 选择交换链格式、颜色空间和分辨率
|
||||
@@ -413,6 +236,10 @@ void Application::createSwapChain() {
|
||||
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
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{};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||
@@ -420,11 +247,11 @@ void Application::createSwapChain() {
|
||||
createInfo.minImageCount = 2; // 双缓冲
|
||||
createInfo.imageFormat = surfaceFormat.format;
|
||||
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.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() };
|
||||
|
||||
if (indices.graphicsFamily != indices.presentFamily) {
|
||||
@@ -477,8 +304,8 @@ void Application::createGraphicsPipeline() {
|
||||
auto fragShaderCode = readFile("shaders/simple_shader.frag.spv");
|
||||
|
||||
// 创建着色器模块
|
||||
VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
|
||||
VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);
|
||||
VkShaderModule vertShaderModule = createShaderModule(this->device, vertShaderCode);
|
||||
VkShaderModule fragShaderModule = createShaderModule(this->device, fragShaderCode);
|
||||
|
||||
// 定义着色器阶段
|
||||
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) {
|
||||
VkCommandBufferBeginInfo beginInfo{};
|
||||
|
||||
+8
-91
@@ -1,106 +1,28 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
#else
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#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();
|
||||
}
|
||||
};
|
||||
#include "AppBase.h"
|
||||
|
||||
|
||||
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:
|
||||
void run();
|
||||
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
GLFWwindow *window;
|
||||
#endif
|
||||
VkInstance instance;
|
||||
|
||||
protected:
|
||||
void initVulkan();
|
||||
void initWindow();
|
||||
void createSurface();
|
||||
void initVulkan();
|
||||
void mainLoop();
|
||||
void cleanup();
|
||||
void createInstance();
|
||||
|
||||
void createImageViews();
|
||||
void createFramebuffers();
|
||||
void createCommandPool();
|
||||
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 createSwapChain();
|
||||
void createPipelineLayout();
|
||||
@@ -129,10 +51,5 @@ private:
|
||||
VkSemaphore renderFinishedSemaphore; // 渲染完成信号量
|
||||
VkFence inFlightFence; // 同步栅栏
|
||||
VkQueue presentQueue; // 呈现队列
|
||||
VkDebugUtilsMessengerEXT debugMessenger;
|
||||
const std::vector<const char*> validationLayers = {
|
||||
"VK_LAYER_KHRONOS_validation"
|
||||
};
|
||||
const uint32_t kWidth = 480;
|
||||
const uint32_t kHeight = 480;
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user