原文地址
Vulkan 与旧版图形 API 的不同之处在于,驱动程序不会为应用执行特定的优化,例如管道重用。 相反,使用 Vulkan 的应用必须自行实现此类优化。 如果不实现,这些应用可能会展现出比运行 OpenGL ES 的应用更差的性能。
在应用自行实现这些优化时,它们可能比驱动程序做得更成功,因为它们可以访问给定用例的更多特定信息。 因此,巧妙地优化使用 Vulkan 的应用可以获得比使用 OpenGL ES 的应用更好的性能。
本页面介绍了您的 Android 应用可以实现的多个优化,以便从 Vulkan 获得性能提升。
渲染时应用屏幕旋转
当应用的向上方向与设备显示画面的方向不匹配时,编译器将旋转应用的交换链图像,使其匹配。 编译器在显示图像时执行此旋转,这会比不旋转消耗更多的电量,有时耗电量会显著增加。
相反,边生成交换链图像边旋转仅会额外消耗很少的电量(如果耗电量增加)。 VkSurfaceCapabilitiesKHR::currentTransform 字段指示编译器应用到窗口的旋转。 在渲染期间应用该旋转后,应用将使用 VkSwapchainCreateInfoKHR::preTransform 字段报告旋转完成。
最大程度减少每个帧的渲染通道
在大多数移动 GPU 架构中,开始和结束渲染通道是一项比较大的开销。 通过将渲染操作组织到尽可能少的渲染通道中,您的应用可以提升性能。
不同的附件加载和附件存储操作会带来不同的性能级别。 例如,如果不需要保留附件的内容,您可以使用更快的 VK_ATTACHMENT_LOAD_OP_CLEAR 或 VK_ATTACHMENT_LOAD_OP_DONT_CARE,而不是 VK_ATTACHMENT_LOAD_OP_LOAD。 类似地,如果不需要将附件的最终值写入内存供日后使用,可以使用 VK_ATTACHMENT_STORE_OP_DONT_CARE 获得比 VK_ATTACHMENT_STORE_OP_STORE 更好的性能。
另外,在大多数渲染通道中,您的应用也不需要加载或存储深度/模板附件。 在此类情况下,如果创建附件图像时使用 VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT 标记,您就不必为附件分配物理内存。 此位提供了与 OpenGL ES 中的 glFramebufferDiscard 相同的优势。
选择合适的内存类型
分配设备内存时,应用必须选择内存类型。内存类型决定应用如何使用内存,也可以说明内存的缓存和附着属性。 不同的设备具有不同的可用内存类型;不同的内存类型会展现不同的性能特性。
应用可以运用简单的算法为给定用途选择最合适的内存类型。 此算法会在 VkPhysicalDeviceMemoryProperties::memoryTypes 数组中选择满足两个条件的第一个内存类型:内存类型必须适用于缓冲区或图像,并且必须至少具备应用需要的属性。
移动系统一般不会为 CPU 和 GPU 设置单独的物理内存堆。 在此类系统上,VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT 的重要性不如在具有离散 GPU 的系统上大,离散 GPU 拥有自己专用的内存。 应用不应假设此属性为必要属性。
按频率将描述符组分组
如果您拥有以不同频率变化的资源绑定,请为每个管道使用多个描述符组,而不是为每个绘图重新绑定所有资源。 例如,您可以为按场景绑定使用一组描述符,为按材料绑定使用另一组描述符,为按网格实例绑定使用第三组描述符。
为最高频率的变更(例如使用每个绘图调用执行的变更)使用立即数常数。