| Flutter Impeller |

pipeline_cache_data_vk_unittests.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 "flutter/fml/build_config.h"
6 #include "flutter/fml/file.h"
7 #include "flutter/testing/testing.h"
8 #include "impeller/playground/playground_test.h"
9 #include "impeller/renderer/backend/vulkan/capabilities_vk.h"
10 #include "impeller/renderer/backend/vulkan/context_vk.h"
11 #include "impeller/renderer/backend/vulkan/pipeline_cache_data_vk.h"
12 #include "impeller/renderer/backend/vulkan/surface_context_vk.h"
13 #include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
14
15 namespace impeller::testing {
16
17 TEST(PipelineCacheDataVKTest, CanTestHeaderCompatibility) {
18 {
19 PipelineCacheHeaderVK a;
20 PipelineCacheHeaderVK b;
21 EXPECT_EQ(a.abi, sizeof(void*));
22 #ifdef FML_ARCH_CPU_64_BITS
23 EXPECT_EQ(a.abi, 8u);
24 #elif FML_ARCH_CPU_32_BITS
25 EXPECT_EQ(a.abi, 4u);
26 #endif
27 EXPECT_TRUE(a.IsCompatibleWith(b));
28 }
29 // Different data sizes don't matter.
30 {
31 PipelineCacheHeaderVK a;
32 PipelineCacheHeaderVK b;
33 a.data_size = b.data_size + 100u;
34 EXPECT_TRUE(a.IsCompatibleWith(b));
35 }
36 // Magic, Driver, vendor, ABI, and UUID matter.
37 {
38 PipelineCacheHeaderVK a;
39 PipelineCacheHeaderVK b;
40 b.magic = 100;
41 EXPECT_FALSE(a.IsCompatibleWith(b));
42 }
43 {
44 PipelineCacheHeaderVK a;
45 PipelineCacheHeaderVK b;
46 b.driver_version = 100;
47 EXPECT_FALSE(a.IsCompatibleWith(b));
48 }
49 {
50 PipelineCacheHeaderVK a;
51 PipelineCacheHeaderVK b;
52 b.vendor_id = 100;
53 EXPECT_FALSE(a.IsCompatibleWith(b));
54 }
55 {
56 PipelineCacheHeaderVK a;
57 PipelineCacheHeaderVK b;
58 b.device_id = 100;
59 EXPECT_FALSE(a.IsCompatibleWith(b));
60 }
61 {
62 PipelineCacheHeaderVK a;
63 PipelineCacheHeaderVK b;
64 b.abi = a.abi / 2u;
65 EXPECT_FALSE(a.IsCompatibleWith(b));
66 }
67 {
68 PipelineCacheHeaderVK a;
69 PipelineCacheHeaderVK b;
70 for (size_t i = 0; i < VK_UUID_SIZE; i++) {
71 b.uuid[i] = a.uuid[i] + 1;
72 }
73 EXPECT_FALSE(a.IsCompatibleWith(b));
74 }
75 }
76
77 TEST(PipelineCacheDataVKTest, CanCreateFromDeviceProperties) {
78 vk::PhysicalDeviceProperties props;
79 std::array<uint8_t, 16> uuid{
80 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
81 };
82 props.pipelineCacheUUID = uuid;
83 props.deviceID = 10;
84 props.vendorID = 11;
85 props.driverVersion = 12;
86 PipelineCacheHeaderVK header(props, 99);
87 EXPECT_EQ(uuid.size(), std::size(header.uuid));
88 EXPECT_EQ(props.deviceID, header.device_id);
89 EXPECT_EQ(props.vendorID, header.vendor_id);
90 EXPECT_EQ(props.driverVersion, header.driver_version);
91 for (size_t i = 0; i < uuid.size(); i++) {
92 EXPECT_EQ(header.uuid[i], uuid.at(i));
93 }
94 }
95
96 TEST(PipelineCacheDataVKTest, WritesIncompleteCacheData) {
97 fml::ScopedTemporaryDirectory temp_dir;
98 auto context = MockVulkanContextBuilder().Build();
99 auto cache = context->GetDevice().createPipelineCacheUnique({});
100 const auto& caps = CapabilitiesVK::Cast(*context->GetCapabilities());
101
102 ASSERT_TRUE(PipelineCacheDataPersist(
103 temp_dir.fd(), caps.GetPhysicalDeviceProperties(), cache.value));
104
105 std::unique_ptr<fml::FileMapping> mapping = fml::FileMapping::CreateReadOnly(
106 temp_dir.fd(), "flutter.impeller.vkcache");
107 ASSERT_TRUE(mapping);
108 PipelineCacheHeaderVK header;
109 ASSERT_GE(mapping->GetSize(), sizeof(header));
110 std::memcpy(&header, mapping->GetMapping(), sizeof(header));
111 ASSERT_EQ(mapping->GetSize(), sizeof(header) + header.data_size);
112 }
113
114 using PipelineCacheDataVKPlaygroundTest = PlaygroundTest;
115 INSTANTIATE_VULKAN_PLAYGROUND_SUITE(PipelineCacheDataVKPlaygroundTest);
116
117 TEST_P(PipelineCacheDataVKPlaygroundTest, CanPersistAndRetrievePipelineCache) {
118 fml::ScopedTemporaryDirectory temp_dir;
119 const auto& surface_context = SurfaceContextVK::Cast(*GetContext());
120 const auto& context_vk = ContextVK::Cast(*surface_context.GetParent());
121 const auto& caps = CapabilitiesVK::Cast(*context_vk.GetCapabilities());
122
123 {
124 auto cache = context_vk.GetDevice().createPipelineCacheUnique({});
125 ASSERT_EQ(cache.result, vk::Result::eSuccess);
126 ASSERT_FALSE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
127 ASSERT_TRUE(PipelineCacheDataPersist(
128 temp_dir.fd(), caps.GetPhysicalDeviceProperties(), cache.value));
129 }
130 ASSERT_TRUE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
131
132 auto mapping = PipelineCacheDataRetrieve(temp_dir.fd(),
133 caps.GetPhysicalDeviceProperties());
134 ASSERT_NE(mapping, nullptr);
135 // Assert that the utility has stripped away the cache header giving us clean
136 // pipeline cache bootstrap information.
137 vk::PipelineCacheHeaderVersionOne vk_cache_header;
138 ASSERT_GE(mapping->GetSize(), sizeof(vk_cache_header));
139 std::memcpy(&vk_cache_header, mapping->GetMapping(), sizeof(vk_cache_header));
140 ASSERT_EQ(vk_cache_header.headerVersion,
141 vk::PipelineCacheHeaderVersion::eOne);
142 }
143
144 TEST_P(PipelineCacheDataVKPlaygroundTest,
145 IntegrityChecksArePerformedOnPersistedData) {
146 fml::ScopedTemporaryDirectory temp_dir;
147 const auto& surface_context = SurfaceContextVK::Cast(*GetContext());
148 const auto& context_vk = ContextVK::Cast(*surface_context.GetParent());
149 const auto& caps = CapabilitiesVK::Cast(*context_vk.GetCapabilities());
150
151 {
152 auto cache = context_vk.GetDevice().createPipelineCacheUnique({});
153 ASSERT_EQ(cache.result, vk::Result::eSuccess);
154 ASSERT_FALSE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
155 ASSERT_TRUE(PipelineCacheDataPersist(
156 temp_dir.fd(), caps.GetPhysicalDeviceProperties(), cache.value));
157 }
158 ASSERT_TRUE(fml::FileExists(temp_dir.fd(), "flutter.impeller.vkcache"));
159 auto incompatible_caps = caps.GetPhysicalDeviceProperties();
160 // Simulate a driver version bump.
161 incompatible_caps.driverVersion =
162 caps.GetPhysicalDeviceProperties().driverVersion + 1u;
163 auto mapping = PipelineCacheDataRetrieve(temp_dir.fd(), incompatible_caps);
164 ASSERT_EQ(mapping, nullptr);
165 }
166
167 } // namespace impeller::testing
capabilities_vk.h
impeller::BackendCast< CapabilitiesVK, Capabilities >::Cast
static CapabilitiesVK & Cast(Capabilities &base)
Definition: backend_cast.h:13
impeller::PlaygroundTest
Definition: playground_test.h:22
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller::testing
Definition: allocation_size_unittests.cc:8
impeller::testing::TEST
TEST(AllocationSizeTest, CanCreateTypedAllocations)
Definition: allocation_size_unittests.cc:10
impeller::testing::TEST_P
TEST_P(AiksTest, DrawAtlasNoColor)
Definition: aiks_dl_atlas_unittests.cc:59
impeller::testing::INSTANTIATE_VULKAN_PLAYGROUND_SUITE
INSTANTIATE_VULKAN_PLAYGROUND_SUITE(DriverInfoVKTest)
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:65
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
playground_test.h
context_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::data_size
uint64_t data_size
Definition: pipeline_cache_data_vk.h:36
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:113
impeller::PipelineCacheHeaderVK::vendor_id
uint32_t vendor_id
Definition: pipeline_cache_data_vk.h:30
impeller::PipelineCacheHeaderVK::uuid
uint8_t uuid[VK_UUID_SIZE]
Definition: pipeline_cache_data_vk.h:35
surface_context_vk.h