|
| 1 | +// Copyright 2013 The Flutter Authors. All rights reserved. |
| 2 | +// Use of this source code is governed by a BSD-style license that can be |
| 3 | +// found in the LICENSE file. |
| 4 | + |
| 5 | +#ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_PIPELINE_CACHE_DATA_VK_H_ |
| 6 | +#define FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_PIPELINE_CACHE_DATA_VK_H_ |
| 7 | + |
| 8 | +#include "flutter/fml/mapping.h" |
| 9 | +#include "flutter/fml/unique_fd.h" |
| 10 | +#include "impeller/renderer/backend/vulkan/vk.h" |
| 11 | + |
| 12 | +namespace impeller { |
| 13 | + |
| 14 | +//------------------------------------------------------------------------------ |
| 15 | +/// @brief An Impeller specific header prepended to all pipeline cache |
| 16 | +/// information that is persisted on disk. This information is used |
| 17 | +/// to perform additional integrity checks that may have been missed |
| 18 | +/// by the Vulkan driver. |
| 19 | +/// |
| 20 | +/// Inspired by |
| 21 | +/// https://medium.com/@zeuxcg/creating-a-robust-pipeline-cache-with-vulkan-961d09416cda. |
| 22 | +/// |
| 23 | +struct PipelineCacheHeaderVK { |
| 24 | + // This can be used by Impeller to manually invalidate all old caches. |
| 25 | + uint32_t magic = 0xC0DEF00D; |
| 26 | + // Notably, this field is missing from checks the Vulkan driver performs. For |
| 27 | + // drivers that don't correctly check the UUID, explicitly disregarding caches |
| 28 | + // generated by previous driver versions sidesteps some landmines. |
| 29 | + uint32_t driver_version = 0; |
| 30 | + uint32_t vendor_id = 0; |
| 31 | + uint32_t device_id = 0; |
| 32 | + // If applications are published as 32-bit and updated via the app store to be |
| 33 | + // 64-bits, this check comes in handy to disregard previous caches. |
| 34 | + uint32_t abi = sizeof(void*); |
| 35 | + uint8_t uuid[VK_UUID_SIZE] = {}; |
| 36 | + uint64_t data_size = 0; |
| 37 | + |
| 38 | + //---------------------------------------------------------------------------- |
| 39 | + /// @brief Constructs a new empty instance. |
| 40 | + /// |
| 41 | + PipelineCacheHeaderVK(); |
| 42 | + |
| 43 | + //---------------------------------------------------------------------------- |
| 44 | + /// @brief Constructs a new instance that will be compatible with the |
| 45 | + /// given physical device properties. |
| 46 | + /// |
| 47 | + /// @param[in] props The properties. |
| 48 | + /// @param[in] p_data_size The data size. |
| 49 | + /// |
| 50 | + explicit PipelineCacheHeaderVK(const VkPhysicalDeviceProperties& props, |
| 51 | + uint64_t p_data_size); |
| 52 | + |
| 53 | + //---------------------------------------------------------------------------- |
| 54 | + /// @brief Determines whether the specified o is compatible with. |
| 55 | + /// |
| 56 | + /// The size of the data following the header may be different and |
| 57 | + /// is not part of compatibility checks. |
| 58 | + /// |
| 59 | + /// @param[in] other The other header. |
| 60 | + /// |
| 61 | + /// @return True if the specified header is compatible with this one, |
| 62 | + /// False otherwise. The size of the data following the header may |
| 63 | + /// be different. |
| 64 | + /// |
| 65 | + bool IsCompatibleWith(const PipelineCacheHeaderVK& other) const; |
| 66 | +}; |
| 67 | + |
| 68 | +//------------------------------------------------------------------------------ |
| 69 | +/// @brief Persist the pipeline cache to a file in the given cache |
| 70 | +/// directory. This function performs integrity checks the Vulkan |
| 71 | +/// driver may have missed. |
| 72 | +/// |
| 73 | +/// @warning The pipeline cache must be externally synchronized for most |
| 74 | +/// complete results. If additional pipelines are being created |
| 75 | +/// while this function is executing, this function may fail to |
| 76 | +/// persist data. |
| 77 | +/// |
| 78 | +/// @param[in] cache_directory The cache directory |
| 79 | +/// @param[in] props The physical device properties |
| 80 | +/// @param[in] cache The cache |
| 81 | +/// |
| 82 | +/// @return If the cache data could be persisted to disk. |
| 83 | +/// |
| 84 | +bool PipelineCacheDataPersist(const fml::UniqueFD& cache_directory, |
| 85 | + const VkPhysicalDeviceProperties& props, |
| 86 | + const vk::UniquePipelineCache& cache); |
| 87 | + |
| 88 | +//------------------------------------------------------------------------------ |
| 89 | +/// @brief Retrieve the previously persisted pipeline cache data. This |
| 90 | +/// function provides integrity checks the Vulkan driver may have |
| 91 | +/// missed. |
| 92 | +/// |
| 93 | +/// The data is stripped of any additional headers that perform |
| 94 | +/// integrity checks. It can be used directly to construct a |
| 95 | +/// pre-initialized Vulkan pipeline cache. |
| 96 | +/// |
| 97 | +/// @param[in] cache_directory The cache directory |
| 98 | +/// @param[in] props The properties |
| 99 | +/// |
| 100 | +/// @return The cache data if it was found and checked to have passed |
| 101 | +/// additional integrity checks. |
| 102 | +/// |
| 103 | +std::unique_ptr<fml::Mapping> PipelineCacheDataRetrieve( |
| 104 | + const fml::UniqueFD& cache_directory, |
| 105 | + const VkPhysicalDeviceProperties& props); |
| 106 | + |
| 107 | +} // namespace impeller |
| 108 | + |
| 109 | +#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_VULKAN_PIPELINE_CACHE_DATA_VK_H_ |
0 commit comments