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 "VkSnapshotApiCall.h" 17 #include "VulkanHandleMapping.h" 18 #include "VulkanHandles.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 clear(); 34 35 void saveReplayBuffers(android::base::Stream* stream); 36 static void loadReplayBuffers(android::base::Stream* stream, 37 std::vector<uint64_t>* outHandleBuffer, 38 std::vector<uint8_t>* outDecoderBuffer); 39 40 enum HandleState { BEGIN = 0, CREATED = 0, BOUND_MEMORY = 1, HANDLE_STATE_COUNT }; 41 42 typedef std::pair<uint64_t, HandleState> HandleWithState; 43 struct HandleWithStateHash { operatorHandleWithStateHash44 inline size_t operator()(const HandleWithState& v) const { 45 std::hash<uint64_t> int_hasher; 46 return int_hasher(v.first) ^ int_hasher(v.second); 47 } 48 }; 49 50 struct HandleReconstruction { 51 std::vector<VkSnapshotApiCallHandle> apiRefs; 52 std::unordered_set<HandleWithState, HandleWithStateHash> childHandles; 53 std::vector<HandleWithState> parentHandles; 54 }; 55 56 struct HandleWithStateReconstruction { 57 std::vector<HandleReconstruction> states = 58 std::vector<HandleReconstruction>(HANDLE_STATE_COUNT); 59 bool delayed_destroy = false; 60 bool destroying = false; 61 }; 62 63 using HandleWithStateReconstructions = 64 android::base::UnpackedComponentManager<32, 16, 16, HandleWithStateReconstruction>; 65 66 struct HandleModification { 67 std::vector<VkSnapshotApiCallHandle> apiRefs; 68 uint32_t order = 0; 69 }; 70 71 using HandleModifications = 72 android::base::UnpackedComponentManager<32, 16, 16, HandleModification>; 73 74 VkSnapshotApiCallInfo* createApiCallInfo(); 75 void destroyApiCallInfo(VkSnapshotApiCallHandle handle); 76 void destroyApiCallInfoIfUnused(VkSnapshotApiCallInfo* info); 77 78 void removeHandleFromApiInfo(VkSnapshotApiCallHandle h, uint64_t toRemove); 79 80 VkSnapshotApiCallInfo* getApiInfo(VkSnapshotApiCallHandle h); 81 82 void setApiTrace(VkSnapshotApiCallInfo* apiInfo, const uint8_t* traceBegin, size_t traceBytes); 83 84 void dump(); 85 86 void addHandles(const uint64_t* toAdd, uint32_t count); 87 void removeHandles(const uint64_t* toRemove, uint32_t count, bool recursive = true); 88 89 void forEachHandleAddApi(const uint64_t* toProcess, uint32_t count, 90 uint64_t VkSnapshotApiCallHandle, HandleState state = CREATED); 91 void forEachHandleDeleteApi(const uint64_t* toProcess, uint32_t count); 92 93 void addHandleDependency(const uint64_t* handles, uint32_t count, uint64_t parentHandle, 94 HandleState childState = CREATED, HandleState parentState = CREATED); 95 96 void setCreatedHandlesForApi(VkSnapshotApiCallHandle handle , const uint64_t* created, 97 uint32_t count); 98 99 void forEachHandleAddModifyApi(const uint64_t* toProcess, uint32_t count, 100 VkSnapshotApiCallHandle handle); 101 102 void forEachHandleClearModifyApi(const uint64_t* toProcess, uint32_t count); 103 104 void setModifiedHandlesForApi(VkSnapshotApiCallHandle handle, const uint64_t* modified, 105 uint32_t count); 106 107 // Used by on_vkCreateDescriptorPool. 108 // 109 // Snapshot keeps track of all the boxed handles created by each function. By default 110 // the generated code assumes no extra internal boxed handles are generated by 111 // VkDecoderGlobalState. But this is not the case for on_vkCreateDescriptorPool. 112 // Thus we add an extra API to VkReconstruction, which gives it the list of all the 113 // extra boxed handles. 114 // 115 // Implementation-wise it is a bit tricky. The regular workflow looks like: 116 // 117 // on_vkCreateDescriptorPool(... pDescriptorPool) 118 // ... 119 // mReconstruction.setCreatedHandlesForApi(OP_vkCreateDescriptorPool, pDescriptorPool); 120 // 121 // It is not easy to directly tell mReconstruction that OP_vkCreateDescriptorPool created 122 // extra handles. Instead, we add an API to VkReconstruction to cache the extra handles. 123 // Next time setCreatedHandlesForApi is called, it will check the cached handles and 124 // add them to OP_vkCreateDescriptorPool. 125 void createExtraHandlesForNextApi(const uint64_t* created, uint32_t count); 126 127 private: 128 std::vector<uint64_t> getOrderedUniqueModifyApis() const; 129 130 VkSnapshotApiCallManager mApiCallManager; 131 132 HandleWithStateReconstructions mHandleReconstructions; 133 HandleModifications mHandleModifications; 134 135 std::vector<uint8_t> mLoadedTrace; 136 }; 137 138 } // namespace vk 139 } // namespace gfxstream 140