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     void removeHandleFromApiInfo(ApiHandle h, uint64_t toRemove);
87 
88     ApiInfo* getApiInfo(ApiHandle h);
89 
90     void setApiTrace(ApiInfo* apiInfo, uint32_t opcode, const uint8_t* traceBegin,
91                      size_t traceBytes);
92 
93     void dump();
94 
95     void addHandles(const uint64_t* toAdd, uint32_t count);
96     void removeHandles(const uint64_t* toRemove, uint32_t count, bool recursive = true);
97 
98     void forEachHandleAddApi(const uint64_t* toProcess, uint32_t count, uint64_t apiHandle,
99                              HandleState state = CREATED);
100     void forEachHandleDeleteApi(const uint64_t* toProcess, uint32_t count);
101 
102     void addHandleDependency(const uint64_t* handles, uint32_t count, uint64_t parentHandle,
103                              HandleState childState = CREATED, HandleState parentState = CREATED);
104 
105     void setCreatedHandlesForApi(uint64_t apiHandle, const uint64_t* created, uint32_t count);
106 
107     void forEachHandleAddModifyApi(const uint64_t* toProcess, uint32_t count, uint64_t apiHandle);
108 
109     void forEachHandleClearModifyApi(const uint64_t* toProcess, uint32_t count);
110 
111     void setModifiedHandlesForApi(uint64_t apiHandle, const uint64_t* modified, uint32_t count);
112 
113     // Used by on_vkCreateDescriptorPool.
114     //
115     // Snapshot keeps track of all the boxed handles created by each function. By default
116     // the generated code assumes no extra internal boxed handles are generated by
117     // VkDecoderGlobalState. But this is not the case for on_vkCreateDescriptorPool.
118     // Thus we add an extra API to VkReconstruction, which gives it the list of all the
119     // extra boxed handles.
120     //
121     // Implementation-wise it is a bit tricky. The regular workflow looks like:
122     //
123     // on_vkCreateDescriptorPool(... pDescriptorPool)
124     // ...
125     // mReconstruction.setCreatedHandlesForApi(OP_vkCreateDescriptorPool, pDescriptorPool);
126     //
127     // It is not easy to directly tell mReconstruction that OP_vkCreateDescriptorPool created
128     // extra handles. Instead, we add an API to VkReconstruction to cache the extra handles.
129     // Next time setCreatedHandlesForApi is called, it will check the cached handles and
130     // add them to OP_vkCreateDescriptorPool.
131     void createExtraHandlesForNextApi(const uint64_t* created, uint32_t count);
132 
133    private:
134     std::vector<uint64_t> getOrderedUniqueModifyApis() const;
135 
136     ApiTrace mApiTrace;
137 
138     HandleWithStateReconstructions mHandleReconstructions;
139     HandleModifications mHandleModifications;
140 
141     std::vector<uint64_t> mExtraHandlesForNextApi;
142 
143     std::vector<uint8_t> mLoadedTrace;
144 };
145 
146 }  // namespace vk
147 }  // namespace gfxstream
148