| Flutter Impeller |

pipeline_cache_data_vk.cc
Go to the documentation of this file.
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 #include "impeller/renderer/backend/vulkan/pipeline_cache_data_vk.h"
6
7 #include "flutter/fml/file.h"
8 #include "impeller/base/allocation.h"
9 #include "impeller/base/validation.h"
10
11 namespace impeller {
12
13 static constexpr const char* kPipelineCacheFileName =
14 "flutter.impeller.vkcache";
15
16 bool PipelineCacheDataPersist(const fml::UniqueFD& cache_directory,
17 const VkPhysicalDeviceProperties& props,
18 const vk::UniquePipelineCache& cache) {
19 if (!cache_directory.is_valid()) {
20 return false;
21 }
22 size_t data_size = 0u;
23 if (cache.getOwner().getPipelineCacheData(*cache, &data_size, nullptr) !=
24 vk::Result::eSuccess) {
25 VALIDATION_LOG << "Could not fetch pipeline cache size.";
26 return false;
27 }
28 if (data_size == 0u) {
29 return true;
30 }
31 auto allocation = std::make_shared<Allocation>();
32 if (!allocation->Truncate(Bytes{sizeof(PipelineCacheHeaderVK) + data_size},
33 false)) {
34 VALIDATION_LOG << "Could not allocate pipeline cache data staging buffer.";
35 return false;
36 }
37 const auto header = PipelineCacheHeaderVK{props, data_size};
38 std::memcpy(allocation->GetBuffer(), &header, sizeof(header));
39 vk::Result lookup_result = cache.getOwner().getPipelineCacheData(
40 *cache, &data_size, allocation->GetBuffer() + sizeof(header));
41
42 // Some drivers may return incomplete erroneously, but this is not an
43 // error condition as some/all data was still written.
44 if (lookup_result != vk::Result::eSuccess &&
45 lookup_result != vk::Result::eIncomplete) {
46 VALIDATION_LOG << "Could not copy pipeline cache data.";
47 return false;
48 }
49
50 auto allocation_mapping = CreateMappingFromAllocation(allocation);
51 if (!allocation_mapping) {
52 return false;
53 }
54 if (!fml::WriteAtomically(cache_directory, kPipelineCacheFileName,
55 *allocation_mapping)) {
56 VALIDATION_LOG << "Could not write cache file to disk.";
57 return false;
58 }
59 return true;
60 }
61
62 std::unique_ptr<fml::Mapping> PipelineCacheDataRetrieve(
63 const fml::UniqueFD& cache_directory,
64 const VkPhysicalDeviceProperties& props) {
65 if (!cache_directory.is_valid()) {
66 return nullptr;
67 }
68 std::shared_ptr<fml::FileMapping> on_disk_data =
69 fml::FileMapping::CreateReadOnly(cache_directory, kPipelineCacheFileName);
70 if (!on_disk_data) {
71 return nullptr;
72 }
73 if (on_disk_data->GetSize() < sizeof(PipelineCacheHeaderVK)) {
74 VALIDATION_LOG << "Pipeline cache data size is too small.";
75 return nullptr;
76 }
77 auto on_disk_header = PipelineCacheHeaderVK{};
78 std::memcpy(&on_disk_header, //
79 on_disk_data->GetMapping(), //
80 sizeof(on_disk_header) //
81 );
82 const auto current_header = PipelineCacheHeaderVK{props, 0u};
83 if (!on_disk_header.IsCompatibleWith(current_header)) {
84 FML_LOG(WARNING)
85 << "Persisted pipeline cache is not compatible with current "
86 "Vulkan context. Ignoring.";
87 return nullptr;
88 }
89 // Zero sized data is known to cause issues.
90 if (on_disk_header.data_size == 0u) {
91 return nullptr;
92 }
93 return std::make_unique<fml::NonOwnedMapping>(
94 on_disk_data->GetMapping() + sizeof(on_disk_header),
95 on_disk_header.data_size, [on_disk_data](auto, auto) {});
96 }
97
98 PipelineCacheHeaderVK::PipelineCacheHeaderVK() = default;
99
100 PipelineCacheHeaderVK::PipelineCacheHeaderVK(
101 const VkPhysicalDeviceProperties& props,
102 uint64_t p_data_size)
103 : driver_version(props.driverVersion),
104 vendor_id(props.vendorID),
105 device_id(props.deviceID),
106 data_size(p_data_size) {
107 std::memcpy(uuid, props.pipelineCacheUUID, VK_UUID_SIZE);
108 }
109
110 bool PipelineCacheHeaderVK::IsCompatibleWith(
111 const PipelineCacheHeaderVK& o) const {
112 // Check for everything but the data size.
113 return magic == o.magic && //
114 driver_version == o.driver_version && //
115 vendor_id == o.vendor_id && //
116 device_id == o.device_id && //
117 abi == o.abi && //
118 std::memcmp(uuid, o.uuid, VK_UUID_SIZE) == 0;
119 }
120
121 } // namespace impeller
allocation.h
impeller::AllocationSize< 1u >
impeller
Definition: allocation.cc:12
impeller::PipelineCacheDataRetrieve
std::unique_ptr< fml::Mapping > PipelineCacheDataRetrieve(const fml::UniqueFD &cache_directory, const VkPhysicalDeviceProperties &props)
Retrieve the previously persisted pipeline cache data. This function provides integrity checks the Vu...
Definition: pipeline_cache_data_vk.cc:62
impeller::CreateMappingFromAllocation
std::shared_ptr< fml::Mapping > CreateMappingFromAllocation(const std::shared_ptr< Allocation > &allocation)
Creates a mapping from allocation.
Definition: allocation.cc:99
impeller::kPipelineCacheFileName
static constexpr const char * kPipelineCacheFileName
Definition: pipeline_cache_data_vk.cc:13
impeller::PipelineCacheDataPersist
bool PipelineCacheDataPersist(const fml::UniqueFD &cache_directory, const VkPhysicalDeviceProperties &props, const vk::UniquePipelineCache &cache)
Persist the pipeline cache to a file in the given cache directory. This function performs integrity c...
Definition: pipeline_cache_data_vk.cc:16
pipeline_cache_data_vk.h
impeller::PipelineCacheHeaderVK
An Impeller specific header prepended to all pipeline cache information that is persisted on disk....
Definition: pipeline_cache_data_vk.h:23
impeller::PipelineCacheHeaderVK::abi
uint32_t abi
Definition: pipeline_cache_data_vk.h:34
impeller::PipelineCacheHeaderVK::driver_version
uint32_t driver_version
Definition: pipeline_cache_data_vk.h:29
impeller::PipelineCacheHeaderVK::device_id
uint32_t device_id
Definition: pipeline_cache_data_vk.h:31
impeller::PipelineCacheHeaderVK::IsCompatibleWith
bool IsCompatibleWith(const PipelineCacheHeaderVK &other) const
Determines whether the specified o is compatible with.
Definition: pipeline_cache_data_vk.cc:110
impeller::PipelineCacheHeaderVK::vendor_id
uint32_t vendor_id
Definition: pipeline_cache_data_vk.h:30
impeller::PipelineCacheHeaderVK::PipelineCacheHeaderVK
PipelineCacheHeaderVK()
Constructs a new empty instance.
impeller::PipelineCacheHeaderVK::magic
uint32_t magic
Definition: pipeline_cache_data_vk.h:25
impeller::PipelineCacheHeaderVK::uuid
uint8_t uuid[VK_UUID_SIZE]
Definition: pipeline_cache_data_vk.h:35
validation.h
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91