blob: d6209d2ed96d0da2b0a44da21e6cf5b5249125cd [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#define FML_USED_ON_EMBEDDER
#include <cstring>
#include <string>
#include <utility>
#include <vector>
#include "embedder.h"
#include "embedder_engine.h"
#include "flutter/fml/synchronization/count_down_latch.h"
#include "flutter/shell/platform/embedder/tests/embedder_config_builder.h"
#include "flutter/shell/platform/embedder/tests/embedder_test.h"
#include "flutter/shell/platform/embedder/tests/embedder_test_context_vulkan.h"
#include "flutter/shell/platform/embedder/tests/embedder_unittests_util.h"
#include "flutter/testing/testing.h"
// CREATE_NATIVE_ENTRY is leaky by design
// NOLINTBEGIN(clang-analyzer-core.StackAddressEscape)
namespace flutter {
namespace testing {
using EmbedderTest = testing::EmbedderTest;
////////////////////////////////////////////////////////////////////////////////
// Notice: Other Vulkan unit tests exist in embedder_gl_unittests.cc.
// See https://github.com/flutter/flutter/issues/134322
////////////////////////////////////////////////////////////////////////////////
namespace {
struct VulkanProcInfo {
decltype(vkGetInstanceProcAddr)* get_instance_proc_addr = nullptr;
decltype(vkGetDeviceProcAddr)* get_device_proc_addr = nullptr;
decltype(vkQueueSubmit)* queue_submit_proc_addr = nullptr;
bool did_call_queue_submit = false;
};
static_assert(std::is_trivially_destructible_v<VulkanProcInfo>);
VulkanProcInfo g_vulkan_proc_info;
VkResult QueueSubmit(VkQueue queue,
uint32_t submitCount,
const VkSubmitInfo* pSubmits,
VkFence fence) {
FML_DCHECK(g_vulkan_proc_info.queue_submit_proc_addr != nullptr);
g_vulkan_proc_info.did_call_queue_submit = true;
return g_vulkan_proc_info.queue_submit_proc_addr(queue, submitCount, pSubmits,
fence);
}
template <size_t N>
int StrcmpFixed(const char* str1, const char (&str2)[N]) {
return strncmp(str1, str2, N - 1);
}
PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
FML_DCHECK(g_vulkan_proc_info.get_device_proc_addr != nullptr);
if (StrcmpFixed(pName, "vkQueueSubmit") == 0) {
g_vulkan_proc_info.queue_submit_proc_addr =
reinterpret_cast<decltype(vkQueueSubmit)*>(
g_vulkan_proc_info.get_device_proc_addr(device, pName));
return reinterpret_cast<PFN_vkVoidFunction>(QueueSubmit);
}
return g_vulkan_proc_info.get_device_proc_addr(device, pName);
}
PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
FML_DCHECK(g_vulkan_proc_info.get_instance_proc_addr != nullptr);
if (StrcmpFixed(pName, "vkGetDeviceProcAddr") == 0) {
g_vulkan_proc_info.get_device_proc_addr =
reinterpret_cast<decltype(vkGetDeviceProcAddr)*>(
g_vulkan_proc_info.get_instance_proc_addr(instance, pName));
return reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr);
}
return g_vulkan_proc_info.get_instance_proc_addr(instance, pName);
}
template <typename T, typename U>
struct CheckSameSignature : std::false_type {};
template <typename Ret, typename... Args>
struct CheckSameSignature<Ret(Args...), Ret(Args...)> : std::true_type {};
static_assert(CheckSameSignature<decltype(GetInstanceProcAddr),
decltype(vkGetInstanceProcAddr)>::value);
static_assert(CheckSameSignature<decltype(GetDeviceProcAddr),
decltype(vkGetDeviceProcAddr)>::value);
static_assert(
CheckSameSignature<decltype(QueueSubmit), decltype(vkQueueSubmit)>::value);
} // namespace
TEST_F(EmbedderTest, CanSwapOutVulkanCalls) {
auto& context = GetEmbedderContext(EmbedderTestContextType::kVulkanContext);
fml::AutoResetWaitableEvent latch;
context.AddIsolateCreateCallback([&latch]() { latch.Signal(); });
EmbedderConfigBuilder builder(context);
builder.SetVulkanRendererConfig(
SkISize::Make(1024, 1024),
[](void* user_data, FlutterVulkanInstanceHandle instance,
const char* name) -> void* {
if (StrcmpFixed(name, "vkGetInstanceProcAddr") == 0) {
g_vulkan_proc_info.get_instance_proc_addr =
reinterpret_cast<decltype(vkGetInstanceProcAddr)*>(
EmbedderTestContextVulkan::InstanceProcAddr(user_data,
instance, name));
return reinterpret_cast<void*>(GetInstanceProcAddr);
}
return EmbedderTestContextVulkan::InstanceProcAddr(user_data, instance,
name);
});
auto engine = builder.LaunchEngine();
ASSERT_TRUE(engine.is_valid());
// Wait for the root isolate to launch.
latch.Wait();
engine.reset();
EXPECT_TRUE(g_vulkan_proc_info.did_call_queue_submit);
}
} // namespace testing
} // namespace flutter
// NOLINTEND(clang-analyzer-core.StackAddressEscape)