Files
face_sdk/vulkan/AppBase.cpp
T

296 lines
9.5 KiB
C++

#include "AppBase.h"
#include <assert.h>
#ifdef _WIN32
#else
#include <android/asset_manager.h>
extern AAssetManager* g_assetManager;
#endif // _WIN32
void VK_CHECK(VkResult ret)
{
assert(ret == VK_SUCCESS);
}
std::vector<char> AppBase::readFile(const std::string& path)
{
std::vector<char> buffer;
#ifdef _WIN32
std::string enginePath = "app/src/main/assets/" + path;
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());
buffer.resize(fileSize);
file.seekg(0);
file.read(buffer.data(), fileSize);
file.close();
#else
AAsset* asset = AAssetManager_open(g_assetManager, path.c_str(), AASSET_MODE_BUFFER);
if (!asset) {
logOut << "Failed to load file: " << path.c_str() << std::endl;
return buffer;
}
size_t length = AAsset_getLength(asset);
buffer.resize(length);
AAsset_read(asset, buffer.data(), length);
AAsset_close(asset);
#endif // _WIN32
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!");
}
}