1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #pragma once
15 
16 #include "VulkanHandleMapping.h"
17 #include "VulkanHandles.h"
18 #include "aemu/base/containers/EntityManager.h"
19 #include "aemu/base/HealthMonitor.h"
20 #include "aemu/base/files/Stream.h"
21 #include "common/goldfish_vk_marshaling.h"
22 #include "utils/GfxApiLogger.h"
23 
24 namespace gfxstream {
25 namespace vk {
26 
27 // A class that captures all important data structures for
28 // reconstructing a Vulkan system state via trimmed API record and replay.
29 class VkReconstruction {
30    public:
31     VkReconstruction();
32 
33     void save(android::base::Stream* stream);
34     void load(android::base::Stream* stream, emugl::GfxApiLogger& gfxLogger,
35               emugl::HealthMonitor<>* healthMonitor);
36 
37     struct ApiInfo {
38         // Fast
39         uint32_t opCode;
40         std::vector<uint8_t> trace;
41         size_t traceBytes = 0;
42         // Book-keeping for which handles were created by this API
43         std::vector<uint64_t> createdHandles;
44     };
45 
46     using ApiTrace = android::base::EntityManager<32, 16, 16, ApiInfo>;
47     using ApiHandle = ApiTrace::EntityHandle;
48 
49     enum HandleState { BEGIN = 0, CREATED = 0, BOUND_MEMORY = 1, HANDLE_STATE_COUNT };
50 
51     typedef std::pair<uint64_t, HandleState> HandleWithState;
52     struct HandleWithStateHash {
operatorHandleWithStateHash53         inline size_t operator()(const HandleWithState& v) const {
54             std::hash<uint64_t> int_hasher;
55             return int_hasher(v.first) ^ int_hasher(v.second);
56         }
57     };
58 
59     struct HandleReconstruction {
60         std::vector<ApiHandle> apiRefs;
61         std::unordered_set<HandleWithState, HandleWithStateHash> childHandles;
62         std::vector<HandleWithState> parentHandles;
63     };
64 
65     struct HandleWithStateReconstruction {
66         std::vector<HandleReconstruction> states =
67             std::vector<HandleReconstruction>(HANDLE_STATE_COUNT);
68         bool delayed_destroy = false;
69         bool destroying = false;
70     };
71 
72     using HandleWithStateReconstructions =
73         android::base::UnpackedComponentManager<32, 16, 16, HandleWithStateReconstruction>;
74 
75     struct HandleModification {
76         std::vector<ApiHandle> apiRefs;
77         uint32_t order = 0;
78     };
79 
80     using HandleModifications =
81         android::base::UnpackedComponentManager<32, 16, 16, HandleModification>;
82 
83     ApiHandle createApiInfo();
84     void destroyApiInfo(ApiHandle h);
85 
86     ApiInfo* getApiInfo(ApiHandle h);
87 
88     void setApiTrace(ApiInfo* apiInfo, uint32_t opcode, const uint8_t* traceBegin,
89                      size_t traceBytes);
90 
91     void dump();
92 
93     void addHandles(const uint64_t* toAdd, uint32_t count);
94     void removeHandles(const uint64_t* toRemove, uint32_t count, bool recursive = true);
95 
96     void forEachHandleAddApi(const uint64_t* toProcess, uint32_t count, uint64_t apiHandle,
97                              HandleState state = CREATED);
98     void forEachHandleDeleteApi(const uint64_t* toProcess, uint32_t count);
99 
100     void addHandleDependency(const uint64_t* handles, uint32_t count, uint64_t parentHandle,
101                              HandleState childState = CREATED, HandleState parentState = CREATED);
102 
103     void setCreatedHandlesForApi(uint64_t apiHandle, const uint64_t* created, uint32_t count);
104 
105     void forEachHandleAddModifyApi(const uint64_t* toProcess, uint32_t count, uint64_t apiHandle);
106 
107     void forEachHandleClearModifyApi(const uint64_t* toProcess, uint32_t count);
108 
109     void setModifiedHandlesForApi(uint64_t apiHandle, const uint64_t* modified, uint32_t count);
110 
111     // Used by on_vkCreateDescriptorPool.
112     //
113     // Snapshot keeps track of all the boxed handles created by each function. By default
114     // the generated code assumes no extra internal boxed handles are generated by
115     // VkDecoderGlobalState. But this is not the case for on_vkCreateDescriptorPool.
116     // Thus we add an extra API to VkReconstruction, which gives it the list of all the
117     // extra boxed handles.
118     //
119     // Implementation-wise it is a bit tricky. The regular workflow looks like:
120     //
121     // on_vkCreateDescriptorPool(... pDescriptorPool)
122     // ...
123     // mReconstruction.setCreatedHandlesForApi(OP_vkCreateDescriptorPool, pDescriptorPool);
124     //
125     // It is not easy to directly tell mReconstruction that OP_vkCreateDescriptorPool created
126     // extra handles. Instead, we add an API to VkReconstruction to cache the extra handles.
127     // Next time setCreatedHandlesForApi is called, it will check the cached handles and
128     // add them to OP_vkCreateDescriptorPool.
129     void createExtraHandlesForNextApi(const uint64_t* created, uint32_t count);
130 
131    private:
132     std::vector<uint64_t> getOrderedUniqueModifyApis() const;
133 
134     ApiTrace mApiTrace;
135 
136     HandleWithStateReconstructions mHandleReconstructions;
137     HandleModifications mHandleModifications;
138 
139     std::vector<uint64_t> mExtraHandlesForNextApi;
140 
141     std::vector<uint8_t> mLoadedTrace;
142 };
143 
144 }  // namespace vk
145 }  // namespace gfxstream
146