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