// Copyright (C) 2019 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include "VulkanHandleMapping.h" #include "VulkanHandles.h" #include "aemu/base/containers/EntityManager.h" #include "aemu/base/HealthMonitor.h" #include "aemu/base/files/Stream.h" #include "common/goldfish_vk_marshaling.h" #include "utils/GfxApiLogger.h" namespace gfxstream { namespace vk { // A class that captures all important data structures for // reconstructing a Vulkan system state via trimmed API record and replay. class VkReconstruction { public: VkReconstruction(); void save(android::base::Stream* stream); void load(android::base::Stream* stream, emugl::GfxApiLogger& gfxLogger, emugl::HealthMonitor<>* healthMonitor); struct ApiInfo { // Fast uint32_t opCode; std::vector trace; size_t traceBytes = 0; // Book-keeping for which handles were created by this API std::vector createdHandles; }; using ApiTrace = android::base::EntityManager<32, 16, 16, ApiInfo>; using ApiHandle = ApiTrace::EntityHandle; enum HandleState { BEGIN = 0, CREATED = 0, BOUND_MEMORY = 1, HANDLE_STATE_COUNT }; typedef std::pair HandleWithState; struct HandleWithStateHash { inline size_t operator()(const HandleWithState& v) const { std::hash int_hasher; return int_hasher(v.first) ^ int_hasher(v.second); } }; struct HandleReconstruction { std::vector apiRefs; std::unordered_set childHandles; std::vector parentHandles; }; struct HandleWithStateReconstruction { std::vector states = std::vector(HANDLE_STATE_COUNT); bool delayed_destroy = false; bool destroying = false; }; using HandleWithStateReconstructions = android::base::UnpackedComponentManager<32, 16, 16, HandleWithStateReconstruction>; struct HandleModification { std::vector apiRefs; uint32_t order = 0; }; using HandleModifications = android::base::UnpackedComponentManager<32, 16, 16, HandleModification>; ApiHandle createApiInfo(); void destroyApiInfo(ApiHandle h); ApiInfo* getApiInfo(ApiHandle h); void setApiTrace(ApiInfo* apiInfo, uint32_t opcode, const uint8_t* traceBegin, size_t traceBytes); void dump(); void addHandles(const uint64_t* toAdd, uint32_t count); void removeHandles(const uint64_t* toRemove, uint32_t count, bool recursive = true); void forEachHandleAddApi(const uint64_t* toProcess, uint32_t count, uint64_t apiHandle, HandleState state = CREATED); void forEachHandleDeleteApi(const uint64_t* toProcess, uint32_t count); void addHandleDependency(const uint64_t* handles, uint32_t count, uint64_t parentHandle, HandleState childState = CREATED, HandleState parentState = CREATED); void setCreatedHandlesForApi(uint64_t apiHandle, const uint64_t* created, uint32_t count); void forEachHandleAddModifyApi(const uint64_t* toProcess, uint32_t count, uint64_t apiHandle); void forEachHandleClearModifyApi(const uint64_t* toProcess, uint32_t count); void setModifiedHandlesForApi(uint64_t apiHandle, const uint64_t* modified, uint32_t count); // Used by on_vkCreateDescriptorPool. // // Snapshot keeps track of all the boxed handles created by each function. By default // the generated code assumes no extra internal boxed handles are generated by // VkDecoderGlobalState. But this is not the case for on_vkCreateDescriptorPool. // Thus we add an extra API to VkReconstruction, which gives it the list of all the // extra boxed handles. // // Implementation-wise it is a bit tricky. The regular workflow looks like: // // on_vkCreateDescriptorPool(... pDescriptorPool) // ... // mReconstruction.setCreatedHandlesForApi(OP_vkCreateDescriptorPool, pDescriptorPool); // // It is not easy to directly tell mReconstruction that OP_vkCreateDescriptorPool created // extra handles. Instead, we add an API to VkReconstruction to cache the extra handles. // Next time setCreatedHandlesForApi is called, it will check the cached handles and // add them to OP_vkCreateDescriptorPool. void createExtraHandlesForNextApi(const uint64_t* created, uint32_t count); private: std::vector getOrderedUniqueModifyApis() const; ApiTrace mApiTrace; HandleWithStateReconstructions mHandleReconstructions; HandleModifications mHandleModifications; std::vector mExtraHandlesForNextApi; std::vector mLoadedTrace; }; } // namespace vk } // namespace gfxstream