做cpa用什么网站家电维修做网站生意怎么样
2026/2/20 5:06:59 网站建设 项目流程
做cpa用什么网站,家电维修做网站生意怎么样,推广产品的方法,苏州网站开发培训欢迎来到第十篇#xff01;两位数里程碑#xff01;在 OpenGL 时代#xff0c;我们习惯了在 C 代码里写一串 GLSL 字符串#xff0c;然后在运行时交给驱动去编译。这种做法虽然方便#xff0c;但有几个大问题#xff1a;各家驱动编译结果不一致#xff1a;N卡能跑的 Sha…欢迎来到第十篇两位数里程碑在 OpenGL 时代我们习惯了在 C 代码里写一串 GLSL 字符串然后在运行时交给驱动去编译。这种做法虽然方便但有几个大问题各家驱动编译结果不一致N卡能跑的 ShaderA卡可能就报错。启动慢每次运行程序都要重新编译 Shader浪费时间。Vulkan 为了解决这些问题引入了强制标准SPIR-V。什么是 SPIR-VSPIR-V 是一种中间语言类似于 Java 的字节码或 .NET 的 MSIL。它是一种二进制格式显卡驱动一定能看懂它。我们的工作流程变成了这样用人类语言GLSL 或 HLSL编写着色器。在开发阶段用编译器把它们编译成.spv文件SPIR-V 二进制文件。在 C 代码中读取这些.spv文件。把二进制数据打包成 Vulkan 的VkShaderModule对象喂给管线。这确保了无论在什么显卡上你的 Shader 行为都是一致的而且加载速度极快。编写 GLSL 着色器为了画出那个三角形我们需要两个最基础的着色器。请在你的 Visual Studio 项目文件夹中和main.cpp在一起新建两个文本文件shader.vert和shader.frag。顶点着色器 (shader.vert)顶点着色器处理每个传入的顶点。它有它的属性比如 模型空间位置颜色法线和纹理坐标作为输入。输出为 剪辑坐标中的最终位置和需要传递的属性 在片段着色器上像颜色和纹理坐标。这些值将 然后通过光栅化器在碎片上进行插值以产生平滑梯度。它的任务是告诉显卡三角形的三个顶点在哪。对于第一个三角形我们不会应用任何变换我们只是 将三个顶点的位置直接指定为规范化设备 创建以下形状的坐标通常情况下我们会通过“顶点缓冲区”把位置传进来。但为了让第一个教程尽可能简单Vulkan 教程采用了一种“作弊”的方法直接把坐标硬编码在 Shader 里。#version 450 // 使用 GLSL 4.50 版本 // 输出变量传递给下一个阶段片元着色器的颜色 // layout(location 0) 指定了它在输出接口中的索引槽位 layout(location 0) out vec3 fragColor; // 硬编码的三角形顶点坐标数组 (2D坐标中心是0,0) vec2 positions[3] vec2[]( vec2(0.0, -0.5), // 顶部 vec2(0.5, 0.5), // 右下 vec2(-0.5, 0.5) // 左下 ); // 硬编码的颜色数组 vec3 colors[3] vec3[]( vec3(1.0, 0.0, 0.0), // 红 vec3(0.0, 1.0, 0.0), // 绿 vec3(0.0, 0.0, 1.0) // 蓝 ); void main() { // gl_VertexIndex 是一个内置变量告诉我们当前处理的是第几个顶点 // 输出位置Vulkan 只需要我们将最终坐标赋值给内置变量 gl_Position // 我们把 2D 坐标补全为 4D 坐标 (x, y, z, w)z0表示在屏幕平面上w1是标准做法 gl_Position vec4(positions[gl_VertexIndex], 0.0, 1.0); // 输出颜色把对应顶点的颜色传给后面 fragColor colors[gl_VertexIndex]; }片元着色器 (shader.frag)它的任务是计算三角形内部每个像素的颜色。光栅化器会自动插值顶点颜色我们只需要把插值后的结果输出即可。#version 450 // 输入变量从顶点着色器传过来的颜色 // 必须和顶点着色器的输出变量类型一致且 location 对应 layout(location 0) in vec3 fragColor; // 输出变量最终显示在屏幕上的颜色RGBA // location 0 对应我们 SwapChain 里的第0个颜色附件 layout(location 0) out vec4 outColor; void main() { // 直接把接收到的 RGB 颜色输出并加上 Alpha1.0 (不透明) outColor vec4(fragColor, 1.0); }编译为 SPIR-V (Windows 之道)现在我们需要把这俩文件编译成显卡认识的.spv文件。Vulkan SDK 自带了一个编译器名叫glslc.exe。它通常位于C:\VulkanSDK\你的版本号\Bin\目录下。为了方便我们在项目目录下创建一个批处理文件compile.bat(Windows用户专属福利)echo off :: 请将下面的路径替换为你实际安装的 Vulkan SDK 路径 set GLSLCC:/VulkanSDK/1.x.xx.x/Bin/glslc.exe echo Compiling vertex shader... %GLSLC% shader.vert -o vert.spv if %errorlevel% neq 0 pause exit /b %errorlevel% echo Compiling fragment shader... %GLSLC% shader.frag -o frag.spv if %errorlevel% neq 0 pause exit /b %errorlevel% echo Compilation successful! pause双击运行这个compile.bat。如果一切顺利你的目录下会多出vert.spv和frag.spv两个文件。这就是我们要的二进制原料。注意以后每次修改了 GLSL 文件记得都要重新运行一下这个脚本回到 C加载二进制文件现在我们需要在 C 里读取这俩文件。这是标准的文件 I/O 操作我们写一个辅助函数来完成请在HelloVulkanApp类定义之前添加这个通用函数并引入必要的头文件#include fstream #include vector // ... 其他 include ... // 辅助函数读取整个二进制文件到一个 vectorchar 中 static std::vectorchar readFile(const std::string filename) { // ate: 打开时定位到文件末尾 (at the end)方便获取文件大小 // binary: 以二进制方式读取 std::ifstream file(filename, std::ios::ate | std::ios::binary); if (!file.is_open()) { throw std::runtime_error(failed to open file: filename); } // 利用 ate 获取文件大小 size_t fileSize (size_t)file.tellg(); std::vectorchar buffer(fileSize); // 回到文件开头开始读取 file.seekg(0); file.read(buffer.data(), fileSize); file.close(); return buffer; } // HelloVulkanApp 类定义开始...创建 Shader Modules读取到二进制数据后我们需要把它包装成 Vulkan 的对象VkShaderModule。在HelloVulkanApp的private区域添加一个辅助函数VkShaderModule createShaderModule(const std::vectorchar code) { VkShaderModuleCreateInfo createInfo{}; createInfo.sType VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; createInfo.codeSize code.size(); // 关键点Vulkan 需要 uint32_t* 类型的指针但我们读出来的是 char*。 // 我们需要用 reinterpret_cast 进行强制转换。 // 只要我们的 vector 数据是按照默认对齐的std::vector通常满足这样做是安全的。 createInfo.pCode reinterpret_castconst 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; }临时整合 (先睹为快)注意Shader Modules 是“用完即弃”的。我们只需要在创建图形管线的那一刻用到它们。一旦管线创建完成这些 Shader Module 就可以而且应该立即销毁以释放内存。因此我们不会把VkShaderModule存储为类的成员变量。我们将在这个漫长的管线创建函数中局部地创建和销毁它们。现在我们先创建一个空的createGraphicsPipeline函数并在initVulkan中调用它看看能不能成功加载文件。void initVulkan() { // ... 之前的步骤 ... createImageViews(); createGraphicsPipeline(); // --- 新增 } // ... 在类中添加这个函数 ... void createGraphicsPipeline() { auto vertShaderCode readFile(vert.spv); auto fragShaderCode readFile(frag.spv); VkShaderModule vertShaderModule createShaderModule(vertShaderCode); VkShaderModule fragShaderModule createShaderModule(fragShaderCode); std::cout 成功加载 Shader! Vertex大小: vertShaderCode.size() , Fragment大小: fragShaderCode.size() std::endl; // 管线创建完成后必须销毁它们 // (当然目前我们还没创建管线但先写上清理代码是个好习惯) vkDestroyShaderModule(device, fragShaderModule, nullptr); vkDestroyShaderModule(device, vertShaderModule, nullptr); }完整代码#define GLFW_INCLUDE_VULKAN #include GLFW/glfw3.h #include iostream #include fstream #include stdexcept #include algorithm #include vector #include cstring #include cstdlib #include cstdint #include limits #include optional #include set const uint32_t WIDTH 800; const uint32_t HEIGHT 600; const std::vectorconst char* validationLayers { VK_LAYER_KHRONOS_validation }; const std::vectorconst char* deviceExtensions { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; #ifdef NDEBUG const bool enableValidationLayers false; #else const bool enableValidationLayers true; #endif 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 DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) { auto func (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, vkDestroyDebugUtilsMessengerEXT); if (func ! nullptr) { func(instance, debugMessenger, pAllocator); } } struct QueueFamilyIndices { std::optionaluint32_t graphicsFamily; std::optionaluint32_t presentFamily; bool isComplete() { return graphicsFamily.has_value() presentFamily.has_value(); } }; struct SwapChainSupportDetails { VkSurfaceCapabilitiesKHR capabilities; std::vectorVkSurfaceFormatKHR formats; std::vectorVkPresentModeKHR presentModes; }; class HelloTriangleApplication { public: void run() { initWindow(); initVulkan(); mainLoop(); cleanup(); } private: GLFWwindow* window; VkInstance instance; VkDebugUtilsMessengerEXT debugMessenger; VkSurfaceKHR surface; VkPhysicalDevice physicalDevice VK_NULL_HANDLE; VkDevice device; VkQueue graphicsQueue; VkQueue presentQueue; VkSwapchainKHR swapChain; std::vectorVkImage swapChainImages; VkFormat swapChainImageFormat; VkExtent2D swapChainExtent; std::vectorVkImageView swapChainImageViews; void initWindow() { glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); window glfwCreateWindow(WIDTH, HEIGHT, Vulkan, nullptr, nullptr); } void initVulkan() { createInstance(); setupDebugMessenger(); createSurface(); pickPhysicalDevice(); createLogicalDevice(); createSwapChain(); createImageViews(); createGraphicsPipeline(); } void mainLoop() { while (!glfwWindowShouldClose(window)) { glfwPollEvents(); } } void cleanup() { for (auto imageView : swapChainImageViews) { vkDestroyImageView(device, imageView, nullptr); } vkDestroySwapchainKHR(device, swapChain, nullptr); vkDestroyDevice(device, nullptr); if (enableValidationLayers) { DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); } vkDestroySurfaceKHR(instance, surface, nullptr); vkDestroyInstance(instance, nullptr); glfwDestroyWindow(window); glfwTerminate(); } void 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 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; VkInstanceCreateInfo createInfo{}; createInfo.sType VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.pApplicationInfo appInfo; auto extensions getRequiredExtensions(); createInfo.enabledExtensionCount static_castuint32_t(extensions.size()); createInfo.ppEnabledExtensionNames extensions.data(); VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; if (enableValidationLayers) { createInfo.enabledLayerCount static_castuint32_t(validationLayers.size()); createInfo.ppEnabledLayerNames validationLayers.data(); populateDebugMessengerCreateInfo(debugCreateInfo); createInfo.pNext (VkDebugUtilsMessengerCreateInfoEXT*) debugCreateInfo; } else { createInfo.enabledLayerCount 0; createInfo.pNext nullptr; } if (vkCreateInstance(createInfo, nullptr, instance) ! VK_SUCCESS) { throw std::runtime_error(failed to create instance!); } } void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT createInfo) { 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; } void setupDebugMessenger() { if (!enableValidationLayers) return; VkDebugUtilsMessengerCreateInfoEXT createInfo; populateDebugMessengerCreateInfo(createInfo); if (CreateDebugUtilsMessengerEXT(instance, createInfo, nullptr, debugMessenger) ! VK_SUCCESS) { throw std::runtime_error(failed to set up debug messenger!); } } void createSurface() { if (glfwCreateWindowSurface(instance, window, nullptr, surface) ! VK_SUCCESS) { throw std::runtime_error(failed to create window surface!); } } void pickPhysicalDevice() { uint32_t deviceCount 0; vkEnumeratePhysicalDevices(instance, deviceCount, nullptr); if (deviceCount 0) { throw std::runtime_error(failed to find GPUs with Vulkan support!); } std::vectorVkPhysicalDevice 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!); } } void createLogicalDevice() { QueueFamilyIndices indices findQueueFamilies(physicalDevice); std::vectorVkDeviceQueueCreateInfo queueCreateInfos; std::setuint32_t uniqueQueueFamilies {indices.graphicsFamily.value(), indices.presentFamily.value()}; float queuePriority 1.0f; for (uint32_t queueFamily : uniqueQueueFamilies) { VkDeviceQueueCreateInfo queueCreateInfo{}; queueCreateInfo.sType VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.queueFamilyIndex queueFamily; queueCreateInfo.queueCount 1; queueCreateInfo.pQueuePriorities queuePriority; queueCreateInfos.push_back(queueCreateInfo); } VkPhysicalDeviceFeatures deviceFeatures{}; VkDeviceCreateInfo createInfo{}; createInfo.sType VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.queueCreateInfoCount static_castuint32_t(queueCreateInfos.size()); createInfo.pQueueCreateInfos queueCreateInfos.data(); createInfo.pEnabledFeatures deviceFeatures; createInfo.enabledExtensionCount static_castuint32_t(deviceExtensions.size()); createInfo.ppEnabledExtensionNames deviceExtensions.data(); if (enableValidationLayers) { createInfo.enabledLayerCount static_castuint32_t(validationLayers.size()); createInfo.ppEnabledLayerNames validationLayers.data(); } else { createInfo.enabledLayerCount 0; } if (vkCreateDevice(physicalDevice, createInfo, nullptr, device) ! VK_SUCCESS) { throw std::runtime_error(failed to create logical device!); } vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, graphicsQueue); vkGetDeviceQueue(device, indices.presentFamily.value(), 0, presentQueue); } void createSwapChain() { SwapChainSupportDetails swapChainSupport querySwapChainSupport(physicalDevice); VkSurfaceFormatKHR surfaceFormat chooseSwapSurfaceFormat(swapChainSupport.formats); VkPresentModeKHR presentMode chooseSwapPresentMode(swapChainSupport.presentModes); VkExtent2D extent chooseSwapExtent(swapChainSupport.capabilities); uint32_t imageCount swapChainSupport.capabilities.minImageCount 1; if (swapChainSupport.capabilities.maxImageCount 0 imageCount swapChainSupport.capabilities.maxImageCount) { imageCount swapChainSupport.capabilities.maxImageCount; } VkSwapchainCreateInfoKHR createInfo{}; createInfo.sType VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; createInfo.surface surface; createInfo.minImageCount imageCount; createInfo.imageFormat surfaceFormat.format; createInfo.imageColorSpace surfaceFormat.colorSpace; createInfo.imageExtent extent; createInfo.imageArrayLayers 1; createInfo.imageUsage VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; QueueFamilyIndices indices findQueueFamilies(physicalDevice); uint32_t queueFamilyIndices[] {indices.graphicsFamily.value(), indices.presentFamily.value()}; if (indices.graphicsFamily ! indices.presentFamily) { createInfo.imageSharingMode VK_SHARING_MODE_CONCURRENT; createInfo.queueFamilyIndexCount 2; createInfo.pQueueFamilyIndices queueFamilyIndices; } else { createInfo.imageSharingMode VK_SHARING_MODE_EXCLUSIVE; } createInfo.preTransform swapChainSupport.capabilities.currentTransform; createInfo.compositeAlpha VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; createInfo.presentMode presentMode; createInfo.clipped VK_TRUE; createInfo.oldSwapchain VK_NULL_HANDLE; if (vkCreateSwapchainKHR(device, createInfo, nullptr, swapChain) ! VK_SUCCESS) { throw std::runtime_error(failed to create swap chain!); } vkGetSwapchainImagesKHR(device, swapChain, imageCount, nullptr); swapChainImages.resize(imageCount); vkGetSwapchainImagesKHR(device, swapChain, imageCount, swapChainImages.data()); swapChainImageFormat surfaceFormat.format; swapChainExtent extent; } void createImageViews() { swapChainImageViews.resize(swapChainImages.size()); for (size_t i 0; i swapChainImages.size(); i) { VkImageViewCreateInfo createInfo{}; createInfo.sType VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; createInfo.image swapChainImages[i]; createInfo.viewType VK_IMAGE_VIEW_TYPE_2D; createInfo.format swapChainImageFormat; createInfo.components.r VK_COMPONENT_SWIZZLE_IDENTITY; createInfo.components.g VK_COMPONENT_SWIZZLE_IDENTITY; createInfo.components.b VK_COMPONENT_SWIZZLE_IDENTITY; createInfo.components.a VK_COMPONENT_SWIZZLE_IDENTITY; createInfo.subresourceRange.aspectMask VK_IMAGE_ASPECT_COLOR_BIT; createInfo.subresourceRange.baseMipLevel 0; createInfo.subresourceRange.levelCount 1; createInfo.subresourceRange.baseArrayLayer 0; createInfo.subresourceRange.layerCount 1; if (vkCreateImageView(device, createInfo, nullptr, swapChainImageViews[i]) ! VK_SUCCESS) { throw std::runtime_error(failed to create image views!); } } } void createGraphicsPipeline() { auto vertShaderCode readFile(shaders/vert.spv); auto fragShaderCode readFile(shaders/frag.spv); VkShaderModule vertShaderModule createShaderModule(vertShaderCode); VkShaderModule fragShaderModule createShaderModule(fragShaderCode); VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; vertShaderStageInfo.sType VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; vertShaderStageInfo.stage VK_SHADER_STAGE_VERTEX_BIT; vertShaderStageInfo.module vertShaderModule; vertShaderStageInfo.pName main; VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; fragShaderStageInfo.sType VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; fragShaderStageInfo.stage VK_SHADER_STAGE_FRAGMENT_BIT; fragShaderStageInfo.module fragShaderModule; fragShaderStageInfo.pName main; VkPipelineShaderStageCreateInfo shaderStages[] {vertShaderStageInfo, fragShaderStageInfo}; vkDestroyShaderModule(device, fragShaderModule, nullptr); vkDestroyShaderModule(device, vertShaderModule, nullptr); } VkShaderModule createShaderModule(const std::vectorchar code) { VkShaderModuleCreateInfo createInfo{}; createInfo.sType VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; createInfo.codeSize code.size(); createInfo.pCode reinterpret_castconst 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; } VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vectorVkSurfaceFormatKHR availableFormats) { for (const auto availableFormat : availableFormats) { if (availableFormat.format VK_FORMAT_B8G8R8A8_SRGB availableFormat.colorSpace VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { return availableFormat; } } return availableFormats[0]; } VkPresentModeKHR chooseSwapPresentMode(const std::vectorVkPresentModeKHR availablePresentModes) { for (const auto availablePresentMode : availablePresentModes) { if (availablePresentMode VK_PRESENT_MODE_MAILBOX_KHR) { return availablePresentMode; } } return VK_PRESENT_MODE_FIFO_KHR; } VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR capabilities) { if (capabilities.currentExtent.width ! std::numeric_limitsuint32_t::max()) { return capabilities.currentExtent; } else { int width, height; glfwGetFramebufferSize(window, width, height); VkExtent2D actualExtent { static_castuint32_t(width), static_castuint32_t(height) }; actualExtent.width std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); actualExtent.height std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); return actualExtent; } } SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) { SwapChainSupportDetails details; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, details.capabilities); 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; } bool isDeviceSuitable(VkPhysicalDevice device) { QueueFamilyIndices indices findQueueFamilies(device); bool extensionsSupported checkDeviceExtensionSupport(device); bool swapChainAdequate false; if (extensionsSupported) { SwapChainSupportDetails swapChainSupport querySwapChainSupport(device); swapChainAdequate !swapChainSupport.formats.empty() !swapChainSupport.presentModes.empty(); } return indices.isComplete() extensionsSupported swapChainAdequate; } bool checkDeviceExtensionSupport(VkPhysicalDevice device) { uint32_t extensionCount; vkEnumerateDeviceExtensionProperties(device, nullptr, extensionCount, nullptr); std::vectorVkExtensionProperties availableExtensions(extensionCount); vkEnumerateDeviceExtensionProperties(device, nullptr, extensionCount, availableExtensions.data()); std::setstd::string requiredExtensions(deviceExtensions.begin(), deviceExtensions.end()); for (const auto extension : availableExtensions) { requiredExtensions.erase(extension.extensionName); } return requiredExtensions.empty(); } QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) { QueueFamilyIndices indices; uint32_t queueFamilyCount 0; vkGetPhysicalDeviceQueueFamilyProperties(device, queueFamilyCount, nullptr); std::vectorVkQueueFamilyProperties 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; } std::vectorconst char* getRequiredExtensions() { uint32_t glfwExtensionCount 0; const char** glfwExtensions; glfwExtensions glfwGetRequiredInstanceExtensions(glfwExtensionCount); std::vectorconst char* extensions(glfwExtensions, glfwExtensions glfwExtensionCount); if (enableValidationLayers) { extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); } return extensions; } bool checkValidationLayerSupport() { uint32_t layerCount; vkEnumerateInstanceLayerProperties(layerCount, nullptr); std::vectorVkLayerProperties 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; } static std::vectorchar readFile(const std::string filename) { std::ifstream file(filename, std::ios::ate | std::ios::binary); if (!file.is_open()) { throw std::runtime_error(failed to open file!); } size_t fileSize (size_t) file.tellg(); std::vectorchar buffer(fileSize); file.seekg(0); file.read(buffer.data(), fileSize); file.close(); return buffer; } 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; } }; int main() { HelloTriangleApplication app; try { app.run(); } catch (const std::exception e) { std::cerr e.what() std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }运行测试确保你已经用compile.bat生成了.spv文件并且它们和你的.exe文件或者 Visual Studio 的项目工作目录在同一个地方。运行程序。如果控制台输出了文件大小并且没有报错恭喜你你已经成功迈出了控制 GPU 的第一步。下一步预告现在手里拿着两个编译好的 Shader Module我们就像拿着两块乐高积木。接下来的任务就是配置一大堆其他的积木光栅化状态、深度模板状态、混合状态等然后把它们拼在一起组成一个完整的Graphics Pipeline。下一篇我们将开始填写那个巨大无比的VkGraphicsPipelineCreateInfo结构体中的第一部分Shader Stage Creation (着色器阶段创建)。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询