274 lines
9.0 KiB
C++
274 lines
9.0 KiB
C++
#include "AppBase.h"
|
|
#include <assert.h>
|
|
|
|
|
|
void VK_CHECK(VkResult ret)
|
|
{
|
|
assert(ret == VK_SUCCESS);
|
|
}
|
|
|
|
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 checkInstanceExtensions() {
|
|
uint32_t extensionCount = 0;
|
|
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
|
|
|
|
std::vector<VkExtensionProperties> extensions(extensionCount);
|
|
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
|
|
|
|
logOut << "Android Available instance extensions:" << std::endl;
|
|
for (const auto& extension : extensions) {
|
|
logOut << "ExtensionName:" << extension.extensionName << " Version:" << extension.specVersion << std::endl;
|
|
}
|
|
}
|
|
|
|
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]);
|
|
}
|
|
#else
|
|
checkInstanceExtensions();
|
|
// Android: 手动添加必要的扩展
|
|
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
|
|
extensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
|
|
|
|
// 可选:添加这些扩展以获得更好的兼容性
|
|
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
|
#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;
|
|
VK_CHECK(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!");
|
|
}
|
|
} |