summaryrefslogtreecommitdiff
path: root/host-common
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2022-03-17 20:02:10 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2022-03-17 20:02:10 +0000
commit843b91d5f83805dbdd60b1451a3c42c62c0fe095 (patch)
treedf51298fe03421f81de0475d9e81b1c02fcda40c /host-common
parent897a7d9ca23e22690a7e2433adc9877d2f0f6bbb (diff)
parent291904d272552a684286390fd5c235fc6c50208d (diff)
downloadvulkan-cereal-843b91d5f83805dbdd60b1451a3c42c62c0fe095.tar.gz
Merge "Add basic renderdoc integration"
Diffstat (limited to 'host-common')
-rw-r--r--host-common/CMakeLists.txt3
-rw-r--r--host-common/RenderDoc.h75
-rw-r--r--host-common/RenderDoc_unittest.cpp89
3 files changed, 166 insertions, 1 deletions
diff --git a/host-common/CMakeLists.txt b/host-common/CMakeLists.txt
index cf100b21..fbd373e3 100644
--- a/host-common/CMakeLists.txt
+++ b/host-common/CMakeLists.txt
@@ -132,7 +132,8 @@ add_executable(
HostAddressSpace_unittest.cpp
HostmemIdMapping_unittest.cpp
logging_unittest.cpp
- GfxstreamFatalError_unittest.cpp)
+ GfxstreamFatalError_unittest.cpp
+ RenderDoc_unittest.cpp)
target_include_directories(
gfxstream-host-common_unittests
diff --git a/host-common/RenderDoc.h b/host-common/RenderDoc.h
new file mode 100644
index 00000000..e141f727
--- /dev/null
+++ b/host-common/RenderDoc.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011-2021 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.
+ */
+#ifndef RENDER_DOC_H
+#define RENDER_DOC_H
+
+#include <renderdoc_app.h>
+
+#include <cstring>
+#include <memory>
+#include <mutex>
+#include <type_traits>
+
+#include "base/SharedLibrary.h"
+#include "host-common/logging.h"
+#include "vulkan/vulkan.h"
+
+using android::base::SharedLibrary;
+
+namespace emugl {
+class RenderDoc {
+ public:
+ using RenderDocApi = RENDERDOC_API_1_4_2;
+ static std::unique_ptr<RenderDoc> create(const SharedLibrary* renderDocLib) {
+ if (!renderDocLib) {
+ ERR("The renderdoc shared library is null.");
+ return nullptr;
+ }
+ pRENDERDOC_GetAPI RENDERDOC_GetAPI =
+ reinterpret_cast<pRENDERDOC_GetAPI>(renderDocLib->findSymbol("RENDERDOC_GetAPI"));
+ if (!RENDERDOC_GetAPI) {
+ ERR("Failed to find the RENDERDOC_GetAPI symbol.");
+ return nullptr;
+ }
+ RenderDocApi* rdocApi = nullptr;
+ int ret =
+ RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_4_2, reinterpret_cast<void**>(&rdocApi));
+ if (ret != 1 || rdocApi == nullptr) {
+ ERR("Failed to load renderdoc API. %d is returned from RENDERDOC_GetAPI.");
+ return nullptr;
+ }
+ return std::unique_ptr<RenderDoc>(new RenderDoc(rdocApi));
+ }
+
+ static constexpr auto kSetActiveWindow = &RenderDocApi::SetActiveWindow;
+ static constexpr auto kGetCaptureOptionU32 = &RenderDocApi::GetCaptureOptionU32;
+ template <class F, class... Args, typename = std::enable_if_t<std::is_invocable_v<F, Args...>>>
+ // Call a RenderDoc in-application API given the function pointer and parameters, and guard the
+ // API call with a mutex.
+ auto call(F(RenderDocApi::*function), Args... args) {
+ std::lock_guard<std::mutex> guard(mMutex);
+ return (mRdocApi->*function)(args...);
+ }
+
+ private:
+ RenderDoc(RenderDocApi* rdocApi) : mRdocApi(rdocApi) {}
+
+ std::mutex mMutex;
+ RenderDocApi* mRdocApi = nullptr;
+};
+} // namespace emugl
+
+#endif
diff --git a/host-common/RenderDoc_unittest.cpp b/host-common/RenderDoc_unittest.cpp
new file mode 100644
index 00000000..8c1fa432
--- /dev/null
+++ b/host-common/RenderDoc_unittest.cpp
@@ -0,0 +1,89 @@
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "RenderDoc.h"
+
+#include <type_traits>
+
+#include "base/SharedLibrary.h"
+
+namespace emugl {
+namespace {
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::InSequence;
+using ::testing::MockFunction;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+using FunctionPtr = android::base::SharedLibrary::FunctionPtr;
+using RenderDocApi = RenderDoc::RenderDocApi;
+
+class MockSharedLibrary : public android::base::SharedLibrary {
+ public:
+ MockSharedLibrary() : SharedLibrary(NULL) {}
+ MOCK_METHOD(FunctionPtr, findSymbol, (const char*), (const, override));
+};
+
+TEST(RenderDocTest, InitializeWithNullSharedLibrary) {
+ EXPECT_EQ(RenderDoc::create(nullptr), nullptr);
+}
+
+TEST(RenderDocTest, CantFindRENDERDOC_GetAPI) {
+ MockSharedLibrary sharedLibrary;
+ EXPECT_CALL(sharedLibrary, findSymbol(_)).WillRepeatedly(Return(nullptr));
+ EXPECT_EQ(RenderDoc::create(&sharedLibrary), nullptr);
+}
+
+TEST(RenderDocTest, RENDERDOC_GetAPIFails) {
+ MockSharedLibrary sharedLibrary;
+ static MockFunction<std::remove_pointer_t<pRENDERDOC_GetAPI>> mockRENDERDOC_GetAPI;
+ static pRENDERDOC_GetAPI fpMockRENDERDOC_GetAPI = [](RENDERDOC_Version version,
+ void** outAPIPointers) {
+ return mockRENDERDOC_GetAPI.Call(version, outAPIPointers);
+ };
+ RenderDocApi rdocApi;
+
+ EXPECT_CALL(sharedLibrary, findSymbol(_)).WillRepeatedly(Return(nullptr));
+ EXPECT_CALL(sharedLibrary, findSymbol("RENDERDOC_GetAPI"))
+ .WillRepeatedly(Return(reinterpret_cast<FunctionPtr>(fpMockRENDERDOC_GetAPI)));
+
+ EXPECT_CALL(mockRENDERDOC_GetAPI, Call(_, _))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(&rdocApi), Return(0)));
+ EXPECT_EQ(RenderDoc::create(&sharedLibrary), nullptr);
+
+ EXPECT_CALL(mockRENDERDOC_GetAPI, Call(_, _))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(nullptr), Return(1)));
+ EXPECT_EQ(RenderDoc::create(&sharedLibrary), nullptr);
+}
+
+TEST(RenderDocTest, CreateSuccessfully) {
+ MockSharedLibrary sharedLibrary;
+ static MockFunction<std::remove_pointer_t<pRENDERDOC_GetAPI>> mockRENDERDOC_GetAPI;
+ static pRENDERDOC_GetAPI fpMockRENDERDOC_GetAPI = [](RENDERDOC_Version version,
+ void** outAPIPointers) {
+ return mockRENDERDOC_GetAPI.Call(version, outAPIPointers);
+ };
+ RenderDocApi rdocApiMock;
+ static MockFunction<std::remove_pointer_t<pRENDERDOC_GetCaptureOptionU32>>
+ getCaptureOptionU32Mock;
+ rdocApiMock.GetCaptureOptionU32 = [](RENDERDOC_CaptureOption option) {
+ return getCaptureOptionU32Mock.Call(option);
+ };
+
+ EXPECT_CALL(sharedLibrary, findSymbol(_)).WillRepeatedly(Return(nullptr));
+ EXPECT_CALL(sharedLibrary, findSymbol("RENDERDOC_GetAPI"))
+ .WillRepeatedly(Return(reinterpret_cast<FunctionPtr>(fpMockRENDERDOC_GetAPI)));
+ EXPECT_CALL(mockRENDERDOC_GetAPI, Call(_, _))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(&rdocApiMock), Return(1)));
+ std::unique_ptr<RenderDoc> renderDoc = RenderDoc::create(&sharedLibrary);
+ EXPECT_NE(renderDoc, nullptr);
+
+ EXPECT_CALL(getCaptureOptionU32Mock, Call(eRENDERDOC_Option_DebugOutputMute))
+ .WillRepeatedly(Return(1));
+ EXPECT_EQ(renderDoc->call(RenderDoc::kGetCaptureOptionU32, eRENDERDOC_Option_DebugOutputMute),
+ 1);
+}
+} // namespace
+} // namespace emugl