diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2022-03-17 20:02:10 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2022-03-17 20:02:10 +0000 |
commit | 843b91d5f83805dbdd60b1451a3c42c62c0fe095 (patch) | |
tree | df51298fe03421f81de0475d9e81b1c02fcda40c /host-common | |
parent | 897a7d9ca23e22690a7e2433adc9877d2f0f6bbb (diff) | |
parent | 291904d272552a684286390fd5c235fc6c50208d (diff) | |
download | vulkan-cereal-843b91d5f83805dbdd60b1451a3c42c62c0fe095.tar.gz |
Merge "Add basic renderdoc integration"
Diffstat (limited to 'host-common')
-rw-r--r-- | host-common/CMakeLists.txt | 3 | ||||
-rw-r--r-- | host-common/RenderDoc.h | 75 | ||||
-rw-r--r-- | host-common/RenderDoc_unittest.cpp | 89 |
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 |