1 /* 2 * Copyright (C) 2011-2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #ifndef RENDER_DOC_H 17 #define RENDER_DOC_H 18 19 #include <renderdoc_app.h> 20 21 #include <algorithm> 22 #include <cstring> 23 #include <memory> 24 #include <mutex> 25 #include <string> 26 #include <type_traits> 27 #include <unordered_map> 28 #include <vector> 29 30 #include "aemu/base/SharedLibrary.h" 31 #include "host-common/logging.h" 32 #include "vulkan/vulkan.h" 33 34 using android::base::SharedLibrary; 35 36 namespace emugl { 37 class RenderDoc { 38 public: 39 using RenderDocApi = RENDERDOC_API_1_4_2; create(const SharedLibrary * renderDocLib)40 static std::unique_ptr<RenderDoc> create(const SharedLibrary* renderDocLib) { 41 if (!renderDocLib) { 42 ERR("The renderdoc shared library is null."); 43 return nullptr; 44 } 45 pRENDERDOC_GetAPI RENDERDOC_GetAPI = 46 reinterpret_cast<pRENDERDOC_GetAPI>(renderDocLib->findSymbol("RENDERDOC_GetAPI")); 47 if (!RENDERDOC_GetAPI) { 48 ERR("Failed to find the RENDERDOC_GetAPI symbol."); 49 return nullptr; 50 } 51 RenderDocApi* rdocApi = nullptr; 52 int ret = 53 RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_4_2, reinterpret_cast<void**>(&rdocApi)); 54 if (ret != 1 || rdocApi == nullptr) { 55 ERR("Failed to load renderdoc API. %d is returned from RENDERDOC_GetAPI."); 56 return nullptr; 57 } 58 return std::unique_ptr<RenderDoc>(new RenderDoc(rdocApi)); 59 } 60 61 static constexpr auto kSetActiveWindow = &RenderDocApi::SetActiveWindow; 62 static constexpr auto kGetCaptureOptionU32 = &RenderDocApi::GetCaptureOptionU32; 63 static constexpr auto kIsFrameCapturing = &RenderDocApi::IsFrameCapturing; 64 static constexpr auto kStartFrameCapture = &RenderDocApi::StartFrameCapture; 65 static constexpr auto kEndFrameCapture = &RenderDocApi::EndFrameCapture; 66 template <class F, class... Args, typename = std::enable_if_t<std::is_invocable_v<F, Args...>>> 67 // Call a RenderDoc in-application API given the function pointer and parameters, and guard the 68 // API call with a mutex. call(F (RenderDocApi::* function),Args...args)69 auto call(F(RenderDocApi::*function), Args... args) const { 70 std::lock_guard<std::mutex> guard(mMutex); 71 return (mRdocApi->*function)(args...); 72 } 73 74 private: RenderDoc(RenderDocApi * rdocApi)75 RenderDoc(RenderDocApi* rdocApi) : mRdocApi(rdocApi) {} 76 77 mutable std::mutex mMutex; 78 RenderDocApi* mRdocApi = nullptr; 79 }; 80 81 template <class RenderDocT> 82 class RenderDocWithMultipleVkInstancesBase { 83 public: RenderDocWithMultipleVkInstancesBase(RenderDocT & renderDoc)84 RenderDocWithMultipleVkInstancesBase(RenderDocT& renderDoc) : mRenderDoc(renderDoc) {} 85 onFrameDelimiter(VkInstance vkInstance)86 void onFrameDelimiter(VkInstance vkInstance) { 87 std::lock_guard<std::mutex> guard(mMutex); 88 mCaptureContexts.erase(vkInstance); 89 if (mRenderDoc.call(RenderDoc::kIsFrameCapturing)) { 90 mCaptureContexts.emplace(vkInstance, 91 std::make_unique<CaptureContext>(mRenderDoc, vkInstance)); 92 } 93 } 94 removeVkInstance(VkInstance vkInstance)95 void removeVkInstance(VkInstance vkInstance) { 96 std::lock_guard<std::mutex> guard(mMutex); 97 mCaptureContexts.erase(vkInstance); 98 } 99 100 private: 101 class CaptureContext { 102 public: CaptureContext(RenderDocT & renderDoc,VkInstance vkInstance)103 CaptureContext(RenderDocT& renderDoc, VkInstance vkInstance) 104 : mRenderDoc(renderDoc), mVkInstance(vkInstance) { 105 mRenderDoc.call(RenderDoc::kStartFrameCapture, 106 RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(mVkInstance), nullptr); 107 } ~CaptureContext()108 ~CaptureContext() { 109 mRenderDoc.call(RenderDoc::kEndFrameCapture, 110 RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(mVkInstance), nullptr); 111 } 112 113 private: 114 const RenderDocT& mRenderDoc; 115 const VkInstance mVkInstance; 116 }; 117 std::mutex mMutex; 118 std::unordered_map<VkInstance, std::unique_ptr<CaptureContext>> mCaptureContexts; 119 RenderDocT& mRenderDoc; 120 }; 121 122 using RenderDocWithMultipleVkInstances = RenderDocWithMultipleVkInstancesBase<RenderDoc>; 123 } // namespace emugl 124 125 #endif 126