aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-07 02:11:15 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2022-04-07 02:11:15 +0000
commita5c3d64061d6c8bbf113c7f9748330951ccda5f0 (patch)
tree1d80c462b6c94031bc36d213f8a2576c62e53972
parent9f5ce4a5aeba8494dc4ed91d641a0f8bbe728140 (diff)
parentb6c73e2de93d8248c066c1c638ec9556f23bdb88 (diff)
downloadqemu-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
-rw-r--r--android/android-emugl/host/libs/libOpenglRender/CMakeLists.txt2
-rw-r--r--android/android-emugl/host/libs/libOpenglRender/vulkan/VkCommonOperations.cpp24
-rw-r--r--android/android-emugl/host/libs/libOpenglRender/vulkan/VkDecoderGlobalState.cpp95
-rw-r--r--android/android-emugl/host/libs/libOpenglRender/vulkan/vk_fn_info.h44
-rw-r--r--android/android-emugl/host/libs/libOpenglRender/vulkan/vk_util.h35
-rw-r--r--android/android-emugl/host/libs/libOpenglRender/vulkan/vk_util_unittest.cpp137
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