// 初始 Skia 封装的后端渲染 vulkan 上下文 if (!grVkBackendContext) { grVkBackendContext = new GrVkBackendContext(); } // 创建 vulkan 应用信息 VkApplicationInfo appCreateInfo = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pNext = nullptr, .pApplicationName = "silk_vulkan", .applicationVersion = VK_MAKE_VERSION(1, 0, 0), .pEngineName = "silk_vulkan_en", .engineVersion = VK_MAKE_VERSION(1, 0, 0), .apiVersion = VK_MAKE_VERSION(1, 0, 0), }; // 创建 Vulkan 实例 uint32_t instanceExtCount = 2; uint32_t deviceExtCount = 1; const char *instanceExt[instanceExtCount]; const char *deviceExt[deviceExtCount]; // 扩展实例支持 android surface,以下都为必选参数 instanceExt[0] = "VK_KHR_surface"; instanceExt[1] = "VK_KHR_android_surface"; // 逻辑设备要支持交换链 deviceExt[0] = "VK_KHR_swapchain"; // 调用 Vulkan 函数创建 VkInstanceCreateInfo instanceCreateInfo{ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pNext = nullptr, .pApplicationInfo = &appCreateInfo, .enabledLayerCount = 0, .ppEnabledLayerNames = nullptr, .enabledExtensionCount = instanceExtCount, .ppEnabledExtensionNames = instanceExt, }; VkResult result = vkCreateInstance( &instanceCreateInfo, nullptr, &grVkBackendContext->fInstance); if (result != VK_SUCCESS) { return false; } // 获取支持的物理设备列表,同一函数调两次,vulkan 用法套路,先取数量再取实际值 uint32_t gpuCount = 0; result = vkEnumeratePhysicalDevices( grVkBackendContext->fInstance, &gpuCount, nullptr); if (result != VK_SUCCESS) { return false; } VkPhysicalDevice vkGpus[gpuCount]; result = vkEnumeratePhysicalDevices( grVkBackendContext->fInstance, &gpuCount, vkGpus); if (result != VK_SUCCESS) { return false; } // 取本机第一个 GPU 物理设备 grVkBackendContext->fPhysicalDevice = vkGpus[0]; VkPhysicalDeviceProperties gpuProperties; vkGetPhysicalDeviceProperties( grVkBackendContext->fPhysicalDevice, &gpuProperties); // 获取物理设备支持的队列族类型,比如用于图形的,用于计算的 uint32_t queueFamilyCount; vkGetPhysicalDeviceQueueFamilyProperties( grVkBackendContext->fPhysicalDevice, &queueFamilyCount, nullptr); if (queueFamilyCount <= 0) { return false; } VkQueueFamilyProperties queueFamilyProperties[queueFamilyCount]; vkGetPhysicalDeviceQueueFamilyProperties( grVkBackendContext->fPhysicalDevice, &queueFamilyCount, queueFamilyProperties); // 我们只关心图形队列族,只需找到图形队列族用于绘制 uint32_t queueFamilyIndex; for (queueFamilyIndex = 0; queueFamilyIndex < queueFamilyCount; queueFamilyIndex++) { if (queueFamilyProperties[queueFamilyIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) { break; } } if (queueFamilyIndex >= queueFamilyCount) { return false; } grVkBackendContext->fGraphicsQueueIndex = queueFamilyIndex; // 队列优先级 0-1 ,高优先级 float priorities[] = { 1.0f, }; VkDeviceQueueCreateInfo queueCreateInfo{ .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, .pNext = nullptr, .flags = 0, .queueFamilyIndex = queueFamilyIndex, .queueCount = 1, .pQueuePriorities = priorities, }; VkDeviceCreateInfo deviceCreateInfo{ .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = nullptr, .queueCreateInfoCount = 1, .pQueueCreateInfos = &queueCreateInfo, .enabledLayerCount = 0, .ppEnabledLayerNames = nullptr, .enabledExtensionCount = deviceExtCount, .ppEnabledExtensionNames = deviceExt, .pEnabledFeatures = nullptr, }; // 创建与物理设备对应的逻辑设备 result = vkCreateDevice( grVkBackendContext->fPhysicalDevice, &deviceCreateInfo, nullptr, &grVkBackendContext->fDevice); if (result != VK_SUCCESS) { return false; } // 初始逻辑设备的队列 vkGetDeviceQueue( grVkBackendContext->fDevice, queueFamilyIndex, 0, &grVkBackendContext->fQueue); // 加载 Vulkan 函数指针(skia 必备,会通过这个来回调各种 vulkan api) // function<void (*(const char *, VkInstance_T *, VkDevice_T *))()> // void (*)() GrVkGetProc getProc = [](const char *name, VkInstance_T *instance, VkDevice_T *device) { if (device != VK_NULL_HANDLE) { return vkGetDeviceProcAddr(device, name); } return vkGetInstanceProcAddr(instance, name); }; grVkBackendContext->fGetProc = getProc;
GrVkExtensions *grVkExtensions = new GrVkExtensions(); grVkExtensions->init( grVkBackendContext->fGetProc, grVkBackendContext->fInstance, grVkBackendContext->fPhysicalDevice, instanceExtCount, instanceExt, deviceExtCount, deviceExt); grVkBackendContext->fVkExtensions = grVkExtensions; // 启用任务拆分,尽可能的利用多线程优化渲染性能 GrContextOptions options; persistentCacheVulkan = new PersistentCacheVulkan(); options.fReduceOpsTaskSplitting = GrContextOptions::Enable::kYes; options.fDisableCoverageCountingPaths = true; options.fDisableDistanceFieldPaths = true; options.fMaxCachedVulkanSecondaryCommandBuffers = 100; options.fReducedShaderVariations = true; options.fPersistentCache = persistentCacheVulkan; // 生成 Skia 所需的 gpu 上下文 grDirectContext = GrDirectContext::MakeVulkan(*grVkBackendContext, options); if (!grDirectContext) { return false; } // 创建 vulkan surface 和 android 关联 VkAndroidSurfaceCreateInfoKHR androidSurfaceCreateInfo{ .sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, .pNext = nullptr, .flags = 0, .window = nativeWindow}; result = vkCreateAndroidSurfaceKHR( grVkBackendContext->fInstance, &androidSurfaceCreateInfo, nullptr, &vkSurfaceKHR); if (result != VK_SUCCESS) { return false; } // 获取 vulkan 所能支持的 surface 能力及属性 VkSurfaceCapabilitiesKHR surfaceCapabilities; result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR( grVkBackendContext->fPhysicalDevice, vkSurfaceKHR, &surfaceCapabilities); if (result != VK_SUCCESS) { return false; } // 获取 vulkan 所能支持的 format 列表 uint32_t formatCount = 0; vkGetPhysicalDeviceSurfaceFormatsKHR( grVkBackendContext->fPhysicalDevice, vkSurfaceKHR, &formatCount, nullptr); VkSurfaceFormatKHR formats[formatCount]; vkGetPhysicalDeviceSurfaceFormatsKHR( grVkBackendContext->fPhysicalDevice, vkSurfaceKHR, &formatCount, formats); // 找到支持 RGBA 的格式 uint32_t chosenFormat; for (chosenFormat = 0; chosenFormat < formatCount; chosenFormat++) { if (formats[chosenFormat].format == VK_FORMAT_R8G8B8A8_UNORM) break; } if (chosenFormat >= formatCount) { return false; } // 需要支持透明从窗口系统继承,而不是自己设置,交换链需要用到该属性 if (surfaceCapabilities.supportedCompositeAlpha != VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) { return false; } // 创建交换链(类似Android中为了解决jank问题,引入的三缓冲机制) VkSwapchainCreateInfoKHR swapchainCreateInfo{ .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, .pNext = nullptr, .surface = vkSurfaceKHR, .minImageCount = surfaceCapabilities.minImageCount, .imageFormat = formats[chosenFormat].format, .imageColorSpace = formats[chosenFormat].colorSpace, .imageExtent = surfaceCapabilities.currentExtent, .imageArrayLayers = 1, .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 1, .pQueueFamilyIndices = &queueFamilyIndex, .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, .compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, .presentMode = VK_PRESENT_MODE_MAILBOX_KHR, .clipped = VK_TRUE, .oldSwapchain = VK_NULL_HANDLE, }; result = vkCreateSwapchainKHR( grVkBackendContext->fDevice, &swapchainCreateInfo, nullptr, &vkSwapchainKHR); if (result != VK_SUCCESS) { return false; } // 获取交换链所有的图像列表 uint32_t swapchainLength; result = vkGetSwapchainImagesKHR( grVkBackendContext->fDevice, vkSwapchainKHR, &swapchainLength, nullptr); if (result != VK_SUCCESS) { return false; } VkImage displayImages[swapchainLength]; result = vkGetSwapchainImagesKHR( grVkBackendContext->fDevice, vkSwapchainKHR, &swapchainLength, displayImages); if (result != VK_SUCCESS) { return false; } // 组装 Skia 的 image 数据(参考了flutter配置) GrVkImageInfo grVkImageInfo; grVkImageInfo.fImage = displayImages[0]; grVkImageInfo.fImageTiling = VK_IMAGE_TILING_OPTIMAL; grVkImageInfo.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; grVkImageInfo.fFormat = VK_FORMAT_R8G8B8A8_UNORM; grVkImageInfo.fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; grVkImageInfo.fSampleCount = 1; grVkImageInfo.fLevelCount = 1; // 组装 Skia 的后端渲染 target GrBackendRenderTarget grBackendRenderTarget(mWidth, mHeight, grVkImageInfo); SkSurfaceProps skSurfaceProps(0, kUnknown_SkPixelGeometry); // 生成 Skia 所需的 sksurface skSurface = SkSurface::MakeFromBackendRenderTarget( grDirectContext.get(), grBackendRenderTarget, kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, SkColorSpace::MakeSRGB(), &skSurfaceProps); if (!skSurface) { return false; } // 获取交换链中下一次可展示的image索引 uint32_t nextIndex; result = vkAcquireNextImageKHR( grVkBackendContext->fDevice, vkSwapchainKHR, UINT64_MAX, VK_NULL_HANDLE, VK_NULL_HANDLE, &nextIndex); if (result != VK_SUCCESS) { return false; } VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; VkSubmitInfo submit_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pNext = nullptr, .waitSemaphoreCount = 0, .pWaitSemaphores = nullptr, .pWaitDstStageMask = &waitStageMask, .commandBufferCount = 0, .pCommandBuffers = nullptr, .signalSemaphoreCount = 0, .pSignalSemaphores = nullptr}; result = vkQueueSubmit(grVkBackendContext->fQueue, 0, &submit_info, nullptr); if (result != VK_SUCCESS) { return false; } // 将 image 提交并显示 VkPresentInfoKHR presentInfo{ .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, .pNext = nullptr, .waitSemaphoreCount = 0, .pWaitSemaphores = nullptr, .swapchainCount = 1, .pSwapchains = &vkSwapchainKHR, .pImageIndices = &nextIndex, .pResults = &result, }; vkQueuePresentKHR(grVkBackendContext->fQueue, &presentInfo);
评论