• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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