diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-07 02:11:15 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2022-04-07 02:11:15 +0000 |
commit | a5c3d64061d6c8bbf113c7f9748330951ccda5f0 (patch) | |
tree | 1d80c462b6c94031bc36d213f8a2576c62e53972 | |
parent | 9f5ce4a5aeba8494dc4ed91d641a0f8bbe728140 (diff) | |
parent | b6c73e2de93d8248c066c1c638ec9556f23bdb88 (diff) | |
download | qemu-snap-temp-L36400000953937803.tar.gz |
Merge "Merge cherrypicks of [2051994, 2055005] into emu-31-stable-release." into emu-31-stable-releasesnap-temp-L36400000953939924snap-temp-L36400000953937803
6 files changed, 259 insertions, 78 deletions
diff --git a/android/android-emugl/host/libs/libOpenglRender/CMakeLists.txt b/android/android-emugl/host/libs/libOpenglRender/CMakeLists.txt index 4f9479d3f2..eea98e3485 100644 --- a/android/android-emugl/host/libs/libOpenglRender/CMakeLists.txt +++ b/android/android-emugl/host/libs/libOpenglRender/CMakeLists.txt @@ -274,7 +274,7 @@ if(NOT LINUX_AARCH64) android_add_test( TARGET OpenglRender_vulkan_unittests SRC # cmake-format: sortable - tests/Vulkan_unittest.cpp vulkan/VulkanStream_unittest.cpp) + tests/Vulkan_unittest.cpp vulkan/VulkanStream_unittest.cpp vulkan/vk_util_unittest.cpp) add_opengl_dependencies(OpenglRender_vulkan_unittests) target_link_libraries(OpenglRender_vulkan_unittests PRIVATE android-emu-test-launcher android-emu) diff --git a/android/android-emugl/host/libs/libOpenglRender/vulkan/VkCommonOperations.cpp b/android/android-emugl/host/libs/libOpenglRender/vulkan/VkCommonOperations.cpp index 9efed4412e..389e27abe2 100644 --- a/android/android-emugl/host/libs/libOpenglRender/vulkan/VkCommonOperations.cpp +++ b/android/android-emugl/host/libs/libOpenglRender/vulkan/VkCommonOperations.cpp @@ -27,6 +27,7 @@ #include "emugl/common/crash_reporter.h" #include "emugl/common/logging.h" #include "emugl/common/vm_operations.h" +#include "vk_util.h" #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> @@ -591,23 +592,12 @@ VkEmulation* createOrGetGlobalVkEmulation(VulkanDispatch* vk) { sVkEmulation->instanceSupportsMoltenVK = moltenVKSupported; if (sVkEmulation->instanceSupportsExternalMemoryCapabilities) { - sVkEmulation->getImageFormatProperties2Func = reinterpret_cast< - PFN_vkGetPhysicalDeviceImageFormatProperties2KHR>( - ivk->vkGetInstanceProcAddr( - sVkEmulation->instance, - "vkGetPhysicalDeviceImageFormatProperties2KHR")); - sVkEmulation->getPhysicalDeviceProperties2Func = reinterpret_cast< - PFN_vkGetPhysicalDeviceProperties2KHR>( - ivk->vkGetInstanceProcAddr( - sVkEmulation->instance, - "vkGetPhysicalDeviceProperties2KHR")); - if (!sVkEmulation->getPhysicalDeviceProperties2Func) { - sVkEmulation->getPhysicalDeviceProperties2Func = reinterpret_cast< - PFN_vkGetPhysicalDeviceProperties2KHR>( - ivk->vkGetInstanceProcAddr( - sVkEmulation->instance, - "vkGetPhysicalDeviceProperties2")); - } + sVkEmulation->getImageFormatProperties2Func = vk_util::getVkInstanceProcAddrWithFallback< + vk_util::vk_fn_info::GetPhysicalDeviceImageFormatProperties2>( + {ivk->vkGetInstanceProcAddr, vk->vkGetInstanceProcAddr}, sVkEmulation->instance); + sVkEmulation->getPhysicalDeviceProperties2Func = vk_util::getVkInstanceProcAddrWithFallback< + vk_util::vk_fn_info::GetPhysicalDeviceProperties2>( + {ivk->vkGetInstanceProcAddr, vk->vkGetInstanceProcAddr}, sVkEmulation->instance); } if (sVkEmulation->instanceSupportsMoltenVK) { diff --git a/android/android-emugl/host/libs/libOpenglRender/vulkan/VkDecoderGlobalState.cpp b/android/android-emugl/host/libs/libOpenglRender/vulkan/VkDecoderGlobalState.cpp index fc0442d656..accbb063cc 100644 --- a/android/android-emugl/host/libs/libOpenglRender/vulkan/VkDecoderGlobalState.cpp +++ b/android/android-emugl/host/libs/libOpenglRender/vulkan/VkDecoderGlobalState.cpp @@ -591,65 +591,42 @@ public: AutoLock lock(mLock); if (m_emu->instanceSupportsExternalMemoryCapabilities) { - - - validPhysicalDevices.erase( - std::remove_if( - validPhysicalDevices.begin(), - validPhysicalDevices.end(), - [instance, vk, - this](VkPhysicalDevice physicalDevice) { - // We can get the device UUID. - VkPhysicalDeviceIDPropertiesKHR idProps = { - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR, - nullptr, - }; - VkPhysicalDeviceProperties2KHR propsWithId = { - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR, - &idProps, - }; - - VkPhysicalDeviceProperties properties; - vk->vkGetPhysicalDeviceProperties( - physicalDevice, &properties); - PFN_vkGetPhysicalDeviceProperties2KHR - getPhysdevProps2Func = nullptr; - if (properties.apiVersion >= - VK_MAKE_VERSION(1, 1, 0)) { - getPhysdevProps2Func = - vk->vkGetPhysicalDeviceProperties2; - if (!getPhysdevProps2Func) { - getPhysdevProps2Func = - (PFN_vkGetPhysicalDeviceProperties2KHR)(vk->vkGetInstanceProcAddr( - instance, - "vkGetPhysicalDeviceProperties2")); - } - } else if (hasInstanceExtension( - instance, - "VK_KHR_get_physical_device_properties2")) { - getPhysdevProps2Func = - vk->vkGetPhysicalDeviceProperties2KHR; - if (!getPhysdevProps2Func) { - getPhysdevProps2Func = - (PFN_vkGetPhysicalDeviceProperties2KHR)(vk->vkGetInstanceProcAddr( - instance, - "vkGetPhysicalDeviceProperties2KHR")); - } - } - if (!getPhysdevProps2Func) { - return false; - } - getPhysdevProps2Func(physicalDevice, - &propsWithId); - - // Remove those devices whose UUIDs don't - // match the one in VkCommonOperations. - return memcmp(m_emu->deviceInfo.idProps - .deviceUUID, - idProps.deviceUUID, - VK_UUID_SIZE) != 0; - }), - validPhysicalDevices.end()); + PFN_vkGetPhysicalDeviceProperties2KHR getPhysdevProps2Func = + vk_util::getVkInstanceProcAddrWithFallback< + vk_util::vk_fn_info::GetPhysicalDeviceProperties2>( + { + vk->vkGetInstanceProcAddr, + m_vk->vkGetInstanceProcAddr, + }, + instance); + + if (getPhysdevProps2Func) { + validPhysicalDevices.erase(std::remove_if( + validPhysicalDevices.begin(), validPhysicalDevices.end(), + [getPhysdevProps2Func, + this](VkPhysicalDevice physicalDevice) { + // We can get the device UUID. + VkPhysicalDeviceIDPropertiesKHR idProps = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR, + nullptr, + }; + VkPhysicalDeviceProperties2KHR propsWithId = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR, + &idProps, + }; + getPhysdevProps2Func(physicalDevice, &propsWithId); + + // Remove those devices whose UUIDs don't match the one + // in VkCommonOperations. + return memcmp(m_emu->deviceInfo.idProps.deviceUUID, + idProps.deviceUUID, VK_UUID_SIZE) != 0; + }), validPhysicalDevices.end()); + } else { + fprintf(stderr, + "%s: warning: failed to " + "vkGetPhysicalDeviceProperties2KHR\n", + __func__); + } } else { // If we don't support ID properties then just advertise only the // first physical device. diff --git a/android/android-emugl/host/libs/libOpenglRender/vulkan/vk_fn_info.h b/android/android-emugl/host/libs/libOpenglRender/vulkan/vk_fn_info.h new file mode 100644 index 0000000000..426ca66b15 --- /dev/null +++ b/android/android-emugl/host/libs/libOpenglRender/vulkan/vk_fn_info.h @@ -0,0 +1,44 @@ +// Copyright 2022 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 VK_FN_INFO_H +#define VK_FN_INFO_H + +#include <vulkan/vulkan.h> + +#include <initializer_list> +#include <tuple> + +namespace vk_util { +namespace vk_fn_info { +template <class T> +struct GetVkFnInfo; + +#define REGISTER_VK_FN_INFO(coreName, allNames) \ + struct coreName; \ + template <> \ + struct GetVkFnInfo<coreName> { \ + static constexpr auto names = std::make_tuple allNames; \ + using type = PFN_vk##coreName; \ + }; + +REGISTER_VK_FN_INFO(GetPhysicalDeviceProperties2, + ("vkGetPhysicalDeviceProperties2KHR", "vkGetPhysicalDeviceProperties2")) +REGISTER_VK_FN_INFO(GetPhysicalDeviceImageFormatProperties2, + ("vkGetPhysicalDeviceImageFormatProperties2KHR", + "vkGetPhysicalDeviceImageFormatProperties2")) +} // namespace vk_fn_info +} // namespace vk_util + +#endif /* VK_FN_INFO_H */
\ No newline at end of file diff --git a/android/android-emugl/host/libs/libOpenglRender/vulkan/vk_util.h b/android/android-emugl/host/libs/libOpenglRender/vulkan/vk_util.h index caf43ea95c..18ab5f9664 100644 --- a/android/android-emugl/host/libs/libOpenglRender/vulkan/vk_util.h +++ b/android/android-emugl/host/libs/libOpenglRender/vulkan/vk_util.h @@ -31,10 +31,15 @@ #include <functional> #include <optional> +#include <string> +#include <tuple> +#include <type_traits> +#include <vector> -#include "common/vk_struct_id.h" #include "VkCommonOperations.h" #include "android/utils/GfxstreamFatalError.h" +#include "common/vk_struct_id.h" +#include "vk_fn_info.h" struct vk_struct_common { VkStructureType sType; @@ -355,6 +360,34 @@ class RecordImageLayoutTransformCommands : public U { nullptr, 0, nullptr, 1, &imageBarrier); } }; + +template <class T> +typename vk_fn_info::GetVkFnInfo<T>::type getVkInstanceProcAddrWithFallback( + const std::vector<std::function<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>>> + &vkGetInstanceProcAddrs, + VkInstance instance) { + for (const auto &vkGetInstanceProcAddr : vkGetInstanceProcAddrs) { + if (!vkGetInstanceProcAddr) { + continue; + } + PFN_vkVoidFunction resWithCurrentVkGetInstanceProcAddr = std::apply( + [&vkGetInstanceProcAddr, instance](auto &&...names) -> PFN_vkVoidFunction { + for (const char *name : {names...}) { + if (PFN_vkVoidFunction resWithCurrentName = + vkGetInstanceProcAddr(instance, name)) { + return resWithCurrentName; + } + } + return nullptr; + }, + vk_fn_info::GetVkFnInfo<T>::names); + if (resWithCurrentVkGetInstanceProcAddr) { + return reinterpret_cast<typename vk_fn_info::GetVkFnInfo<T>::type>( + resWithCurrentVkGetInstanceProcAddr); + } + } + return nullptr; +} } // namespace vk_util #endif /* VK_UTIL_H */ diff --git a/android/android-emugl/host/libs/libOpenglRender/vulkan/vk_util_unittest.cpp b/android/android-emugl/host/libs/libOpenglRender/vulkan/vk_util_unittest.cpp new file mode 100644 index 0000000000..f56b5fb6aa --- /dev/null +++ b/android/android-emugl/host/libs/libOpenglRender/vulkan/vk_util_unittest.cpp @@ -0,0 +1,137 @@ +// Copyright 2022 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. + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include "vk_util.h" + +#include <tuple> + +namespace vk_util { +namespace vk_fn_info { + +// Register a fake Vulkan function for testing. +using PFN_vkGfxstreamTestFunc = PFN_vkCreateDevice; +REGISTER_VK_FN_INFO(GfxstreamTestFunc, ("vkGfxstreamTestFunc", "vkGfxstreamTestFuncGOOGLE", + "vkGfxstreamTestFuncGFXSTREAM")) +constexpr auto vkGfxstreamTestFuncNames = vk_fn_info::GetVkFnInfo<GfxstreamTestFunc>::names; + +namespace { +using ::testing::_; +using ::testing::MockFunction; +using ::testing::Return; +using ::testing::StrEq; +using ::testing::StrNe; + +TEST(getVkInstanceProcAddrWithFallbackTest, ShouldReturnNullOnFailure) { + VkInstance instance = reinterpret_cast<VkInstance>(0x1234'0000); + MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrAlwaysNULL; + + EXPECT_CALL(vkGetInstanceProcAddrAlwaysNULL, Call(instance, _)).WillRepeatedly(Return(nullptr)); + + EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>({}, instance), nullptr); + EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>({nullptr, nullptr}, instance), + nullptr); + EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>( + {vkGetInstanceProcAddrAlwaysNULL.AsStdFunction(), + vkGetInstanceProcAddrAlwaysNULL.AsStdFunction()}, + instance), + nullptr); +} + +TEST(getVkInstanceProcAddrWithFallbackTest, ShouldSkipNullVkGetInstanceProcAddr) { + VkInstance instance = reinterpret_cast<VkInstance>(0x1234'0000); + PFN_vkGfxstreamTestFunc validFp = reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x4321'0000); + MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrMock; + + EXPECT_CALL(vkGetInstanceProcAddrMock, Call(instance, _)) + .WillRepeatedly(Return(reinterpret_cast<PFN_vkVoidFunction>(validFp))); + + EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>( + {nullptr, vkGetInstanceProcAddrMock.AsStdFunction()}, instance), + validFp); + EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>( + {vkGetInstanceProcAddrMock.AsStdFunction(), nullptr}, instance), + validFp); +} + +TEST(getVkInstanceProcAddrWithFallbackTest, ShouldSkipNullFpReturned) { + VkInstance instance = reinterpret_cast<VkInstance>(0x1234'0000); + PFN_vkGfxstreamTestFunc validFp = reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x4321'0000); + MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrMock; + MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrAlwaysNULL; + + // We know that vkGfxstreamTest has different names. + EXPECT_CALL(vkGetInstanceProcAddrMock, + Call(instance, StrNe(std::get<1>(vkGfxstreamTestFuncNames)))) + .WillRepeatedly(Return(nullptr)); + EXPECT_CALL(vkGetInstanceProcAddrMock, + Call(instance, StrEq(std::get<1>(vkGfxstreamTestFuncNames)))) + .WillRepeatedly(Return(reinterpret_cast<PFN_vkVoidFunction>(validFp))); + EXPECT_CALL(vkGetInstanceProcAddrAlwaysNULL, Call(instance, _)).WillRepeatedly(Return(nullptr)); + + EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>( + {vkGetInstanceProcAddrMock.AsStdFunction(), + vkGetInstanceProcAddrAlwaysNULL.AsStdFunction()}, + instance), + validFp); + EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>( + {vkGetInstanceProcAddrAlwaysNULL.AsStdFunction(), + vkGetInstanceProcAddrMock.AsStdFunction()}, + instance), + validFp); +} + +TEST(getVkInstanceProcAddrWithFallbackTest, firstVkInstanceProcAddrShouldTakeThePriority) { + VkInstance instance = reinterpret_cast<VkInstance>(0x1234'0000); + PFN_vkGfxstreamTestFunc validFp1 = reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x4321'0000); + PFN_vkGfxstreamTestFunc validFp2 = reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x3421'0070); + MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrMock1; + MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrMock2; + + EXPECT_CALL(vkGetInstanceProcAddrMock1, Call(instance, _)) + .WillRepeatedly(Return(reinterpret_cast<PFN_vkVoidFunction>(validFp1))); + EXPECT_CALL(vkGetInstanceProcAddrMock2, Call(instance, _)) + .WillRepeatedly(Return(reinterpret_cast<PFN_vkVoidFunction>(validFp2))); + + EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>( + {vkGetInstanceProcAddrMock1.AsStdFunction(), + vkGetInstanceProcAddrMock2.AsStdFunction()}, + instance), + validFp1); +} + +TEST(getVkInstanceProcAddrWithFallbackTest, firstNameShouldTakeThePriority) { + VkInstance instance = reinterpret_cast<VkInstance>(0x1234'0000); + PFN_vkGfxstreamTestFunc validFps[] = {reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x4321'0000), + reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x3421'0070), + reinterpret_cast<PFN_vkGfxstreamTestFunc>(0x2222'4321)}; + MockFunction<std::remove_pointer_t<PFN_vkGetInstanceProcAddr>> vkGetInstanceProcAddrMock; + + EXPECT_CALL(vkGetInstanceProcAddrMock, + Call(instance, StrEq(std::get<0>(vkGfxstreamTestFuncNames)))) + .WillRepeatedly(Return(reinterpret_cast<PFN_vkVoidFunction>(validFps[0]))); + ON_CALL(vkGetInstanceProcAddrMock, Call(instance, StrEq(std::get<1>(vkGfxstreamTestFuncNames)))) + .WillByDefault(Return(reinterpret_cast<PFN_vkVoidFunction>(validFps[1]))); + ON_CALL(vkGetInstanceProcAddrMock, Call(instance, StrEq(std::get<2>(vkGfxstreamTestFuncNames)))) + .WillByDefault(Return(reinterpret_cast<PFN_vkVoidFunction>(validFps[2]))); + + EXPECT_EQ(getVkInstanceProcAddrWithFallback<GfxstreamTestFunc>( + {vkGetInstanceProcAddrMock.AsStdFunction()}, instance), + validFps[0]); +} +} // namespace +} // namespace vk_fn_info +} // namespace vk_util |