[Impeller] add basic Impeller+Vulkan support to embedder API. (flutter/engine#55490)
Works on GLFW example app with no validation errors.
This commit is contained in:
parent
2c6a76e3d1
commit
23641d582a
@ -44764,6 +44764,8 @@ ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_software.cc +
|
|||||||
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_software.h + ../../../flutter/LICENSE
|
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_software.h + ../../../flutter/LICENSE
|
||||||
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.cc + ../../../flutter/LICENSE
|
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.cc + ../../../flutter/LICENSE
|
||||||
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.h + ../../../flutter/LICENSE
|
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.h + ../../../flutter/LICENSE
|
||||||
|
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan_impeller.cc + ../../../flutter/LICENSE
|
||||||
|
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan_impeller.h + ../../../flutter/LICENSE
|
||||||
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_task_runner.cc + ../../../flutter/LICENSE
|
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_task_runner.cc + ../../../flutter/LICENSE
|
||||||
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_task_runner.h + ../../../flutter/LICENSE
|
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_task_runner.h + ../../../flutter/LICENSE
|
||||||
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_thread_host.cc + ../../../flutter/LICENSE
|
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_thread_host.cc + ../../../flutter/LICENSE
|
||||||
@ -47655,6 +47657,8 @@ FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.cc
|
|||||||
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.h
|
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_software.h
|
||||||
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.cc
|
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.cc
|
||||||
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.h
|
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan.h
|
||||||
|
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan_impeller.cc
|
||||||
|
FILE: ../../../flutter/shell/platform/embedder/embedder_surface_vulkan_impeller.h
|
||||||
FILE: ../../../flutter/shell/platform/embedder/embedder_task_runner.cc
|
FILE: ../../../flutter/shell/platform/embedder/embedder_task_runner.cc
|
||||||
FILE: ../../../flutter/shell/platform/embedder/embedder_task_runner.h
|
FILE: ../../../flutter/shell/platform/embedder/embedder_task_runner.h
|
||||||
FILE: ../../../flutter/shell/platform/embedder/embedder_thread_host.cc
|
FILE: ../../../flutter/shell/platform/embedder/embedder_thread_host.cc
|
||||||
|
@ -16,7 +16,14 @@ namespace impeller {
|
|||||||
static constexpr const char* kInstanceLayer = "ImpellerInstance";
|
static constexpr const char* kInstanceLayer = "ImpellerInstance";
|
||||||
|
|
||||||
CapabilitiesVK::CapabilitiesVK(bool enable_validations,
|
CapabilitiesVK::CapabilitiesVK(bool enable_validations,
|
||||||
bool fatal_missing_validations) {
|
bool fatal_missing_validations,
|
||||||
|
bool use_embedder_extensions,
|
||||||
|
std::vector<std::string> instance_extensions,
|
||||||
|
std::vector<std::string> device_extensions)
|
||||||
|
: use_embedder_extensions_(use_embedder_extensions),
|
||||||
|
embedder_instance_extensions_(std::move(instance_extensions)),
|
||||||
|
embedder_device_extensions_(std::move(device_extensions)) {
|
||||||
|
if (!use_embedder_extensions_) {
|
||||||
auto extensions = vk::enumerateInstanceExtensionProperties();
|
auto extensions = vk::enumerateInstanceExtensionProperties();
|
||||||
auto layers = vk::enumerateInstanceLayerProperties();
|
auto layers = vk::enumerateInstanceLayerProperties();
|
||||||
|
|
||||||
@ -39,6 +46,11 @@ CapabilitiesVK::CapabilitiesVK(bool enable_validations,
|
|||||||
exts_[layer_name].insert(layer_ext.extensionName);
|
exts_[layer_name].insert(layer_ext.extensionName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for (const auto& ext : embedder_instance_extensions_) {
|
||||||
|
exts_[kInstanceLayer].insert(ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
validations_enabled_ =
|
validations_enabled_ =
|
||||||
enable_validations && HasLayer("VK_LAYER_KHRONOS_validation");
|
enable_validations && HasLayer("VK_LAYER_KHRONOS_validation");
|
||||||
@ -239,17 +251,25 @@ static std::optional<std::set<std::string>> GetSupportedDeviceExtensions(
|
|||||||
std::optional<std::vector<std::string>>
|
std::optional<std::vector<std::string>>
|
||||||
CapabilitiesVK::GetEnabledDeviceExtensions(
|
CapabilitiesVK::GetEnabledDeviceExtensions(
|
||||||
const vk::PhysicalDevice& physical_device) const {
|
const vk::PhysicalDevice& physical_device) const {
|
||||||
auto exts = GetSupportedDeviceExtensions(physical_device);
|
std::set<std::string> exts;
|
||||||
|
|
||||||
if (!exts.has_value()) {
|
if (!use_embedder_extensions_) {
|
||||||
|
auto maybe_exts = GetSupportedDeviceExtensions(physical_device);
|
||||||
|
|
||||||
|
if (!maybe_exts.has_value()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
exts = maybe_exts.value();
|
||||||
|
} else {
|
||||||
|
exts = std::set(embedder_device_extensions_.begin(),
|
||||||
|
embedder_device_extensions_.end());
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> enabled;
|
std::vector<std::string> enabled;
|
||||||
|
|
||||||
auto for_each_common_extension = [&](RequiredCommonDeviceExtensionVK ext) {
|
auto for_each_common_extension = [&](RequiredCommonDeviceExtensionVK ext) {
|
||||||
auto name = GetExtensionName(ext);
|
auto name = GetExtensionName(ext);
|
||||||
if (exts->find(name) == exts->end()) {
|
if (exts.find(name) == exts.end()) {
|
||||||
VALIDATION_LOG << "Device does not support required extension: " << name;
|
VALIDATION_LOG << "Device does not support required extension: " << name;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -260,7 +280,7 @@ CapabilitiesVK::GetEnabledDeviceExtensions(
|
|||||||
auto for_each_android_extension = [&](RequiredAndroidDeviceExtensionVK ext) {
|
auto for_each_android_extension = [&](RequiredAndroidDeviceExtensionVK ext) {
|
||||||
#ifdef FML_OS_ANDROID
|
#ifdef FML_OS_ANDROID
|
||||||
auto name = GetExtensionName(ext);
|
auto name = GetExtensionName(ext);
|
||||||
if (exts->find(name) == exts->end()) {
|
if (exts.find(name) == exts.end()) {
|
||||||
VALIDATION_LOG << "Device does not support required Android extension: "
|
VALIDATION_LOG << "Device does not support required Android extension: "
|
||||||
<< name;
|
<< name;
|
||||||
return false;
|
return false;
|
||||||
@ -272,7 +292,7 @@ CapabilitiesVK::GetEnabledDeviceExtensions(
|
|||||||
|
|
||||||
auto for_each_optional_extension = [&](OptionalDeviceExtensionVK ext) {
|
auto for_each_optional_extension = [&](OptionalDeviceExtensionVK ext) {
|
||||||
auto name = GetExtensionName(ext);
|
auto name = GetExtensionName(ext);
|
||||||
if (exts->find(name) != exts->end()) {
|
if (exts.find(name) != exts.end()) {
|
||||||
enabled.push_back(name);
|
enabled.push_back(name);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -524,27 +544,36 @@ bool CapabilitiesVK::SetPhysicalDevice(
|
|||||||
required_common_device_extensions_.clear();
|
required_common_device_extensions_.clear();
|
||||||
required_android_device_extensions_.clear();
|
required_android_device_extensions_.clear();
|
||||||
optional_device_extensions_.clear();
|
optional_device_extensions_.clear();
|
||||||
auto exts = GetSupportedDeviceExtensions(device);
|
|
||||||
if (!exts.has_value()) {
|
std::set<std::string> exts;
|
||||||
|
if (!use_embedder_extensions_) {
|
||||||
|
auto maybe_exts = GetSupportedDeviceExtensions(device);
|
||||||
|
if (!maybe_exts.has_value()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
exts = maybe_exts.value();
|
||||||
|
} else {
|
||||||
|
exts = std::set(embedder_device_extensions_.begin(),
|
||||||
|
embedder_device_extensions_.end());
|
||||||
|
}
|
||||||
|
|
||||||
IterateExtensions<RequiredCommonDeviceExtensionVK>([&](auto ext) -> bool {
|
IterateExtensions<RequiredCommonDeviceExtensionVK>([&](auto ext) -> bool {
|
||||||
auto ext_name = GetExtensionName(ext);
|
auto ext_name = GetExtensionName(ext);
|
||||||
if (exts->find(ext_name) != exts->end()) {
|
if (exts.find(ext_name) != exts.end()) {
|
||||||
required_common_device_extensions_.insert(ext);
|
required_common_device_extensions_.insert(ext);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](auto ext) -> bool {
|
IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](auto ext) -> bool {
|
||||||
auto ext_name = GetExtensionName(ext);
|
auto ext_name = GetExtensionName(ext);
|
||||||
if (exts->find(ext_name) != exts->end()) {
|
if (exts.find(ext_name) != exts.end()) {
|
||||||
required_android_device_extensions_.insert(ext);
|
required_android_device_extensions_.insert(ext);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
IterateExtensions<OptionalDeviceExtensionVK>([&](auto ext) -> bool {
|
IterateExtensions<OptionalDeviceExtensionVK>([&](auto ext) -> bool {
|
||||||
auto ext_name = GetExtensionName(ext);
|
auto ext_name = GetExtensionName(ext);
|
||||||
if (exts->find(ext_name) != exts->end()) {
|
if (exts.find(ext_name) != exts.end()) {
|
||||||
optional_device_extensions_.insert(ext);
|
optional_device_extensions_.insert(ext);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -170,7 +170,10 @@ class CapabilitiesVK final : public Capabilities,
|
|||||||
public BackendCast<CapabilitiesVK, Capabilities> {
|
public BackendCast<CapabilitiesVK, Capabilities> {
|
||||||
public:
|
public:
|
||||||
explicit CapabilitiesVK(bool enable_validations,
|
explicit CapabilitiesVK(bool enable_validations,
|
||||||
bool fatal_missing_validations = false);
|
bool fatal_missing_validations = false,
|
||||||
|
bool use_embedder_extensions = false,
|
||||||
|
std::vector<std::string> instance_extensions = {},
|
||||||
|
std::vector<std::string> device_extensions = {});
|
||||||
|
|
||||||
~CapabilitiesVK();
|
~CapabilitiesVK();
|
||||||
|
|
||||||
@ -293,6 +296,12 @@ class CapabilitiesVK final : public Capabilities,
|
|||||||
ISize max_render_pass_attachment_size_ = ISize{0, 0};
|
ISize max_render_pass_attachment_size_ = ISize{0, 0};
|
||||||
bool is_valid_ = false;
|
bool is_valid_ = false;
|
||||||
|
|
||||||
|
// The embedder.h API is responsible for providing the instance and device
|
||||||
|
// extensions.
|
||||||
|
bool use_embedder_extensions_ = false;
|
||||||
|
std::vector<std::string> embedder_instance_extensions_;
|
||||||
|
std::vector<std::string> embedder_device_extensions_;
|
||||||
|
|
||||||
bool HasExtension(const std::string& ext) const;
|
bool HasExtension(const std::string& ext) const;
|
||||||
|
|
||||||
bool HasLayer(const std::string& layer) const;
|
bool HasLayer(const std::string& layer) const;
|
||||||
|
@ -160,8 +160,19 @@ void ContextVK::Setup(Settings settings) {
|
|||||||
auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER;
|
auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER;
|
||||||
dispatcher.init(settings.proc_address_callback);
|
dispatcher.init(settings.proc_address_callback);
|
||||||
|
|
||||||
|
std::vector<std::string> embedder_instance_extensions;
|
||||||
|
std::vector<std::string> embedder_device_extensions;
|
||||||
|
if (settings.embedder_data.has_value()) {
|
||||||
|
embedder_instance_extensions = settings.embedder_data->instance_extensions;
|
||||||
|
embedder_device_extensions = settings.embedder_data->device_extensions;
|
||||||
|
}
|
||||||
auto caps = std::shared_ptr<CapabilitiesVK>(new CapabilitiesVK(
|
auto caps = std::shared_ptr<CapabilitiesVK>(new CapabilitiesVK(
|
||||||
settings.enable_validation, settings.fatal_missing_validations));
|
settings.enable_validation, //
|
||||||
|
settings.fatal_missing_validations, //
|
||||||
|
/*use_embedder_extensions=*/settings.embedder_data.has_value(), //
|
||||||
|
embedder_instance_extensions, //
|
||||||
|
embedder_device_extensions //
|
||||||
|
));
|
||||||
|
|
||||||
if (!caps->IsValid()) {
|
if (!caps->IsValid()) {
|
||||||
VALIDATION_LOG << "Could not determine device capabilities.";
|
VALIDATION_LOG << "Could not determine device capabilities.";
|
||||||
@ -226,7 +237,7 @@ void ContextVK::Setup(Settings settings) {
|
|||||||
instance_info.setFlags(instance_flags);
|
instance_info.setFlags(instance_flags);
|
||||||
|
|
||||||
auto device_holder = std::make_shared<DeviceHolderImpl>();
|
auto device_holder = std::make_shared<DeviceHolderImpl>();
|
||||||
{
|
if (!settings.embedder_data.has_value()) {
|
||||||
auto instance = vk::createInstanceUnique(instance_info);
|
auto instance = vk::createInstanceUnique(instance_info);
|
||||||
if (instance.result != vk::Result::eSuccess) {
|
if (instance.result != vk::Result::eSuccess) {
|
||||||
VALIDATION_LOG << "Could not create Vulkan instance: "
|
VALIDATION_LOG << "Could not create Vulkan instance: "
|
||||||
@ -234,6 +245,9 @@ void ContextVK::Setup(Settings settings) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
device_holder->instance = std::move(instance.value);
|
device_holder->instance = std::move(instance.value);
|
||||||
|
} else {
|
||||||
|
device_holder->instance.reset(settings.embedder_data->instance);
|
||||||
|
device_holder->owned = false;
|
||||||
}
|
}
|
||||||
dispatcher.init(device_holder->instance.get());
|
dispatcher.init(device_holder->instance.get());
|
||||||
|
|
||||||
@ -254,7 +268,7 @@ void ContextVK::Setup(Settings settings) {
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
/// Pick the physical device.
|
/// Pick the physical device.
|
||||||
///
|
///
|
||||||
{
|
if (!settings.embedder_data.has_value()) {
|
||||||
auto physical_device =
|
auto physical_device =
|
||||||
PickPhysicalDevice(*caps, device_holder->instance.get());
|
PickPhysicalDevice(*caps, device_holder->instance.get());
|
||||||
if (!physical_device.has_value()) {
|
if (!physical_device.has_value()) {
|
||||||
@ -262,6 +276,8 @@ void ContextVK::Setup(Settings settings) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
device_holder->physical_device = physical_device.value();
|
device_holder->physical_device = physical_device.value();
|
||||||
|
} else {
|
||||||
|
device_holder->physical_device = settings.embedder_data->physical_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -320,7 +336,7 @@ void ContextVK::Setup(Settings settings) {
|
|||||||
device_info.setPEnabledExtensionNames(enabled_device_extensions_c);
|
device_info.setPEnabledExtensionNames(enabled_device_extensions_c);
|
||||||
// Device layers are deprecated and ignored.
|
// Device layers are deprecated and ignored.
|
||||||
|
|
||||||
{
|
if (!settings.embedder_data.has_value()) {
|
||||||
auto device_result =
|
auto device_result =
|
||||||
device_holder->physical_device.createDeviceUnique(device_info);
|
device_holder->physical_device.createDeviceUnique(device_info);
|
||||||
if (device_result.result != vk::Result::eSuccess) {
|
if (device_result.result != vk::Result::eSuccess) {
|
||||||
@ -328,6 +344,8 @@ void ContextVK::Setup(Settings settings) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
device_holder->device = std::move(device_result.value);
|
device_holder->device = std::move(device_result.value);
|
||||||
|
} else {
|
||||||
|
device_holder->device.reset(settings.embedder_data->device);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!caps->SetPhysicalDevice(device_holder->physical_device,
|
if (!caps->SetPhysicalDevice(device_holder->physical_device,
|
||||||
@ -413,11 +431,18 @@ void ContextVK::Setup(Settings settings) {
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
/// Fetch the queues.
|
/// Fetch the queues.
|
||||||
///
|
///
|
||||||
QueuesVK queues(device_holder->device.get(), //
|
QueuesVK queues;
|
||||||
|
if (!settings.embedder_data.has_value()) {
|
||||||
|
queues = QueuesVK::FromQueueIndices(device_holder->device.get(), //
|
||||||
graphics_queue.value(), //
|
graphics_queue.value(), //
|
||||||
compute_queue.value(), //
|
compute_queue.value(), //
|
||||||
transfer_queue.value() //
|
transfer_queue.value() //
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
queues =
|
||||||
|
QueuesVK::FromEmbedderQueue(settings.embedder_data->queue,
|
||||||
|
settings.embedder_data->queue_family_index);
|
||||||
|
}
|
||||||
if (!queues.IsValid()) {
|
if (!queues.IsValid()) {
|
||||||
VALIDATION_LOG << "Could not fetch device queues.";
|
VALIDATION_LOG << "Could not fetch device queues.";
|
||||||
return;
|
return;
|
||||||
|
@ -45,6 +45,17 @@ class ContextVK final : public Context,
|
|||||||
public BackendCast<ContextVK, Context>,
|
public BackendCast<ContextVK, Context>,
|
||||||
public std::enable_shared_from_this<ContextVK> {
|
public std::enable_shared_from_this<ContextVK> {
|
||||||
public:
|
public:
|
||||||
|
/// Embedder Stuff
|
||||||
|
struct EmbedderData {
|
||||||
|
VkInstance instance;
|
||||||
|
VkPhysicalDevice physical_device;
|
||||||
|
VkDevice device;
|
||||||
|
uint32_t queue_family_index;
|
||||||
|
VkQueue queue;
|
||||||
|
std::vector<std::string> instance_extensions;
|
||||||
|
std::vector<std::string> device_extensions;
|
||||||
|
};
|
||||||
|
|
||||||
struct Settings {
|
struct Settings {
|
||||||
PFN_vkGetInstanceProcAddr proc_address_callback = nullptr;
|
PFN_vkGetInstanceProcAddr proc_address_callback = nullptr;
|
||||||
std::vector<std::shared_ptr<fml::Mapping>> shader_libraries_data;
|
std::vector<std::shared_ptr<fml::Mapping>> shader_libraries_data;
|
||||||
@ -55,6 +66,8 @@ class ContextVK final : public Context,
|
|||||||
/// If validations are requested but cannot be enabled, log a fatal error.
|
/// If validations are requested but cannot be enabled, log a fatal error.
|
||||||
bool fatal_missing_validations = false;
|
bool fatal_missing_validations = false;
|
||||||
|
|
||||||
|
std::optional<EmbedderData> embedder_data;
|
||||||
|
|
||||||
Settings() = default;
|
Settings() = default;
|
||||||
|
|
||||||
Settings(Settings&&) = default;
|
Settings(Settings&&) = default;
|
||||||
@ -207,9 +220,17 @@ class ContextVK final : public Context,
|
|||||||
return physical_device;
|
return physical_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~DeviceHolderImpl() {
|
||||||
|
if (!owned) {
|
||||||
|
instance.release();
|
||||||
|
device.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vk::UniqueInstance instance;
|
vk::UniqueInstance instance;
|
||||||
vk::PhysicalDevice physical_device;
|
vk::PhysicalDevice physical_device;
|
||||||
vk::UniqueDevice device;
|
vk::UniqueDevice device;
|
||||||
|
bool owned = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<DeviceHolderImpl> device_holder_;
|
std::shared_ptr<DeviceHolderImpl> device_holder_;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "impeller/renderer/backend/vulkan/command_pool_vk.h"
|
#include "impeller/renderer/backend/vulkan/command_pool_vk.h"
|
||||||
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
||||||
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
|
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
|
||||||
|
#include "vulkan/vulkan_core.h"
|
||||||
|
|
||||||
namespace impeller {
|
namespace impeller {
|
||||||
namespace testing {
|
namespace testing {
|
||||||
@ -260,6 +261,48 @@ TEST(ContextVKTest, HasDefaultColorFormat) {
|
|||||||
ASSERT_NE(capabilites_vk->GetDefaultColorFormat(), PixelFormat::kUnknown);
|
ASSERT_NE(capabilites_vk->GetDefaultColorFormat(), PixelFormat::kUnknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ContextVKTest, EmbedderOverridesUsesInstanceExtensions) {
|
||||||
|
ContextVK::EmbedderData data;
|
||||||
|
auto other_context = MockVulkanContextBuilder().Build();
|
||||||
|
|
||||||
|
data.instance = other_context->GetInstance();
|
||||||
|
data.device = other_context->GetDevice();
|
||||||
|
data.physical_device = other_context->GetPhysicalDevice();
|
||||||
|
data.queue = VkQueue{};
|
||||||
|
data.queue_family_index = 0;
|
||||||
|
// Missing surface extension.
|
||||||
|
data.instance_extensions = {};
|
||||||
|
data.device_extensions = {"VK_KHR_swapchain"};
|
||||||
|
|
||||||
|
ScopedValidationDisable scoped;
|
||||||
|
auto context = MockVulkanContextBuilder().SetEmbedderData(data).Build();
|
||||||
|
|
||||||
|
EXPECT_EQ(context, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ContextVKTest, EmbedderOverrides) {
|
||||||
|
ContextVK::EmbedderData data;
|
||||||
|
auto other_context = MockVulkanContextBuilder().Build();
|
||||||
|
|
||||||
|
data.instance = other_context->GetInstance();
|
||||||
|
data.device = other_context->GetDevice();
|
||||||
|
data.physical_device = other_context->GetPhysicalDevice();
|
||||||
|
data.queue = VkQueue{};
|
||||||
|
data.queue_family_index = 0;
|
||||||
|
data.instance_extensions = {"VK_KHR_surface",
|
||||||
|
"VK_KHR_portability_enumeration"};
|
||||||
|
data.device_extensions = {"VK_KHR_swapchain"};
|
||||||
|
|
||||||
|
auto context = MockVulkanContextBuilder().SetEmbedderData(data).Build();
|
||||||
|
|
||||||
|
EXPECT_TRUE(context->IsValid());
|
||||||
|
EXPECT_EQ(context->GetInstance(), other_context->GetInstance());
|
||||||
|
EXPECT_EQ(context->GetDevice(), other_context->GetDevice());
|
||||||
|
EXPECT_EQ(context->GetPhysicalDevice(), other_context->GetPhysicalDevice());
|
||||||
|
EXPECT_EQ(context->GetGraphicsQueue()->GetIndex().index, 0u);
|
||||||
|
EXPECT_EQ(context->GetGraphicsQueue()->GetIndex().family, 0u);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ContextVKTest, BatchSubmitCommandBuffersOnArm) {
|
TEST(ContextVKTest, BatchSubmitCommandBuffersOnArm) {
|
||||||
std::shared_ptr<ContextVK> context =
|
std::shared_ptr<ContextVK> context =
|
||||||
MockVulkanContextBuilder()
|
MockVulkanContextBuilder()
|
||||||
|
@ -16,6 +16,18 @@
|
|||||||
|
|
||||||
namespace impeller {
|
namespace impeller {
|
||||||
|
|
||||||
|
constexpr std::optional<PixelFormat> VkFormatToImpellerFormat(
|
||||||
|
vk::Format format) {
|
||||||
|
switch (format) {
|
||||||
|
case vk::Format::eR8G8B8A8Unorm:
|
||||||
|
return PixelFormat::kR8G8B8A8UNormInt;
|
||||||
|
case vk::Format::eB8G8R8A8Unorm:
|
||||||
|
return PixelFormat::kB8G8R8A8UNormInt;
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constexpr vk::SampleCountFlagBits ToVKSampleCountFlagBits(SampleCount count) {
|
constexpr vk::SampleCountFlagBits ToVKSampleCountFlagBits(SampleCount count) {
|
||||||
switch (count) {
|
switch (count) {
|
||||||
case SampleCount::kCount1:
|
case SampleCount::kCount1:
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "impeller/renderer/backend/vulkan/queue_vk.h"
|
#include "impeller/renderer/backend/vulkan/queue_vk.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
||||||
|
|
||||||
namespace impeller {
|
namespace impeller {
|
||||||
@ -45,7 +47,24 @@ void QueueVK::InsertDebugMarker(std::string_view label) const {
|
|||||||
|
|
||||||
QueuesVK::QueuesVK() = default;
|
QueuesVK::QueuesVK() = default;
|
||||||
|
|
||||||
QueuesVK::QueuesVK(const vk::Device& device,
|
QueuesVK::QueuesVK(std::shared_ptr<QueueVK> graphics_queue,
|
||||||
|
std::shared_ptr<QueueVK> compute_queue,
|
||||||
|
std::shared_ptr<QueueVK> transfer_queue)
|
||||||
|
: graphics_queue(std::move(graphics_queue)),
|
||||||
|
compute_queue(std::move(compute_queue)),
|
||||||
|
transfer_queue(std::move(transfer_queue)) {}
|
||||||
|
|
||||||
|
// static
|
||||||
|
QueuesVK QueuesVK::FromEmbedderQueue(vk::Queue queue,
|
||||||
|
uint32_t queue_family_index) {
|
||||||
|
auto graphics_queue = std::make_shared<QueueVK>(
|
||||||
|
QueueIndexVK{.family = queue_family_index, .index = 0}, queue);
|
||||||
|
|
||||||
|
return QueuesVK(graphics_queue, graphics_queue, graphics_queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
QueuesVK QueuesVK::FromQueueIndices(const vk::Device& device,
|
||||||
QueueIndexVK graphics,
|
QueueIndexVK graphics,
|
||||||
QueueIndexVK compute,
|
QueueIndexVK compute,
|
||||||
QueueIndexVK transfer) {
|
QueueIndexVK transfer) {
|
||||||
@ -54,10 +73,11 @@ QueuesVK::QueuesVK(const vk::Device& device,
|
|||||||
auto vk_transfer = device.getQueue(transfer.family, transfer.index);
|
auto vk_transfer = device.getQueue(transfer.family, transfer.index);
|
||||||
|
|
||||||
// Always set up the graphics queue.
|
// Always set up the graphics queue.
|
||||||
graphics_queue = std::make_shared<QueueVK>(graphics, vk_graphics);
|
auto graphics_queue = std::make_shared<QueueVK>(graphics, vk_graphics);
|
||||||
ContextVK::SetDebugName(device, vk_graphics, "ImpellerGraphicsQ");
|
ContextVK::SetDebugName(device, vk_graphics, "ImpellerGraphicsQ");
|
||||||
|
|
||||||
// Setup the compute queue if its different from the graphics queue.
|
// Setup the compute queue if its different from the graphics queue.
|
||||||
|
std::shared_ptr<QueueVK> compute_queue;
|
||||||
if (compute == graphics) {
|
if (compute == graphics) {
|
||||||
compute_queue = graphics_queue;
|
compute_queue = graphics_queue;
|
||||||
} else {
|
} else {
|
||||||
@ -67,6 +87,7 @@ QueuesVK::QueuesVK(const vk::Device& device,
|
|||||||
|
|
||||||
// Setup the transfer queue if its different from the graphics or compute
|
// Setup the transfer queue if its different from the graphics or compute
|
||||||
// queues.
|
// queues.
|
||||||
|
std::shared_ptr<QueueVK> transfer_queue;
|
||||||
if (transfer == graphics) {
|
if (transfer == graphics) {
|
||||||
transfer_queue = graphics_queue;
|
transfer_queue = graphics_queue;
|
||||||
} else if (transfer == compute) {
|
} else if (transfer == compute) {
|
||||||
@ -75,6 +96,9 @@ QueuesVK::QueuesVK(const vk::Device& device,
|
|||||||
transfer_queue = std::make_shared<QueueVK>(transfer, vk_transfer);
|
transfer_queue = std::make_shared<QueueVK>(transfer, vk_transfer);
|
||||||
ContextVK::SetDebugName(device, vk_transfer, "ImpellerTransferQ");
|
ContextVK::SetDebugName(device, vk_transfer, "ImpellerTransferQ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return QueuesVK(std::move(graphics_queue), std::move(compute_queue),
|
||||||
|
std::move(transfer_queue));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QueuesVK::IsValid() const {
|
bool QueuesVK::IsValid() const {
|
||||||
|
@ -67,7 +67,14 @@ struct QueuesVK {
|
|||||||
|
|
||||||
QueuesVK();
|
QueuesVK();
|
||||||
|
|
||||||
QueuesVK(const vk::Device& device,
|
QueuesVK(std::shared_ptr<QueueVK> graphics_queue,
|
||||||
|
std::shared_ptr<QueueVK> compute_queue,
|
||||||
|
std::shared_ptr<QueueVK> transfer_queue);
|
||||||
|
|
||||||
|
static QueuesVK FromEmbedderQueue(vk::Queue queue,
|
||||||
|
uint32_t queue_family_index);
|
||||||
|
|
||||||
|
static QueuesVK FromQueueIndices(const vk::Device& device,
|
||||||
QueueIndexVK graphics,
|
QueueIndexVK graphics,
|
||||||
QueueIndexVK compute,
|
QueueIndexVK compute,
|
||||||
QueueIndexVK transfer);
|
QueueIndexVK transfer);
|
||||||
|
@ -82,13 +82,17 @@ std::unique_ptr<Surface> SurfaceContextVK::AcquireNextSurface() {
|
|||||||
if (!surface) {
|
if (!surface) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
MarkFrameEnd();
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfaceContextVK::MarkFrameEnd() {
|
||||||
if (auto pipeline_library = parent_->GetPipelineLibrary()) {
|
if (auto pipeline_library = parent_->GetPipelineLibrary()) {
|
||||||
impeller::PipelineLibraryVK::Cast(*pipeline_library)
|
impeller::PipelineLibraryVK::Cast(*pipeline_library)
|
||||||
.DidAcquireSurfaceFrame();
|
.DidAcquireSurfaceFrame();
|
||||||
}
|
}
|
||||||
parent_->DisposeThreadLocalCachedResources();
|
parent_->DisposeThreadLocalCachedResources();
|
||||||
parent_->GetResourceAllocator()->DebugTraceMemoryStatistics();
|
parent_->GetResourceAllocator()->DebugTraceMemoryStatistics();
|
||||||
return surface;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceContextVK::UpdateSurfaceSize(const ISize& size) const {
|
void SurfaceContextVK::UpdateSurfaceSize(const ISize& size) const {
|
||||||
|
@ -76,6 +76,12 @@ class SurfaceContextVK : public Context,
|
|||||||
|
|
||||||
std::unique_ptr<Surface> AcquireNextSurface();
|
std::unique_ptr<Surface> AcquireNextSurface();
|
||||||
|
|
||||||
|
/// @brief Performs frame incrementing processes like AcquireNextSurface but
|
||||||
|
/// without the surface.
|
||||||
|
///
|
||||||
|
/// Used by the embedder.h implementations.
|
||||||
|
void MarkFrameEnd();
|
||||||
|
|
||||||
/// @brief Mark the current swapchain configuration as dirty, forcing it to be
|
/// @brief Mark the current swapchain configuration as dirty, forcing it to be
|
||||||
/// recreated on the next frame.
|
/// recreated on the next frame.
|
||||||
void UpdateSurfaceSize(const ISize& size) const;
|
void UpdateSurfaceSize(const ISize& size) const;
|
||||||
|
@ -928,6 +928,7 @@ std::shared_ptr<ContextVK> MockVulkanContextBuilder::Build() {
|
|||||||
g_instance_layers = instance_layers_;
|
g_instance_layers = instance_layers_;
|
||||||
g_format_properties_callback = format_properties_callback_;
|
g_format_properties_callback = format_properties_callback_;
|
||||||
g_physical_device_properties_callback = physical_properties_callback_;
|
g_physical_device_properties_callback = physical_properties_callback_;
|
||||||
|
settings.embedder_data = embedder_data_;
|
||||||
std::shared_ptr<ContextVK> result = ContextVK::Create(std::move(settings));
|
std::shared_ptr<ContextVK> result = ContextVK::Create(std::move(settings));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -108,10 +108,17 @@ class MockVulkanContextBuilder {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MockVulkanContextBuilder SetEmbedderData(
|
||||||
|
const ContextVK::EmbedderData& embedder_data) {
|
||||||
|
embedder_data_ = embedder_data;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::function<void(ContextVK::Settings&)> settings_callback_;
|
std::function<void(ContextVK::Settings&)> settings_callback_;
|
||||||
std::vector<std::string> instance_extensions_;
|
std::vector<std::string> instance_extensions_;
|
||||||
std::vector<std::string> instance_layers_;
|
std::vector<std::string> instance_layers_;
|
||||||
|
std::optional<ContextVK::EmbedderData> embedder_data_;
|
||||||
std::function<void(VkPhysicalDevice physicalDevice,
|
std::function<void(VkPhysicalDevice physicalDevice,
|
||||||
VkFormat format,
|
VkFormat format,
|
||||||
VkFormatProperties* pFormatProperties)>
|
VkFormatProperties* pFormatProperties)>
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "impeller/renderer/backend/vulkan/texture_vk.h"
|
#include "impeller/renderer/backend/vulkan/texture_vk.h"
|
||||||
|
|
||||||
|
#include "impeller/core/texture_descriptor.h"
|
||||||
#include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
|
#include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
|
||||||
#include "impeller/renderer/backend/vulkan/formats_vk.h"
|
#include "impeller/renderer/backend/vulkan/formats_vk.h"
|
||||||
#include "impeller/renderer/backend/vulkan/sampler_vk.h"
|
#include "impeller/renderer/backend/vulkan/sampler_vk.h"
|
||||||
|
@ -68,18 +68,14 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceVulkan::AcquireFrame(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceFrame::EncodeCallback encode_callback =
|
SurfaceFrame::EncodeCallback encode_callback = [](const SurfaceFrame&,
|
||||||
[image = image, delegate = delegate_](const SurfaceFrame&,
|
|
||||||
DlCanvas* canvas) -> bool {
|
DlCanvas* canvas) -> bool {
|
||||||
if (canvas == nullptr) {
|
if (canvas == nullptr) {
|
||||||
FML_DLOG(ERROR) << "Canvas not available.";
|
FML_DLOG(ERROR) << "Canvas not available.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas->Flush();
|
canvas->Flush();
|
||||||
|
return true;
|
||||||
return delegate->PresentImage(reinterpret_cast<VkImage>(image.image),
|
|
||||||
static_cast<VkFormat>(image.format));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SurfaceFrame::SubmitCallback submit_callback =
|
SurfaceFrame::SubmitCallback submit_callback =
|
||||||
|
@ -4,17 +4,52 @@
|
|||||||
|
|
||||||
#include "flutter/shell/gpu/gpu_surface_vulkan_impeller.h"
|
#include "flutter/shell/gpu/gpu_surface_vulkan_impeller.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "flow/surface_frame.h"
|
#include "flow/surface_frame.h"
|
||||||
#include "flutter/fml/make_copyable.h"
|
#include "flutter/fml/make_copyable.h"
|
||||||
|
#include "fml/trace_event.h"
|
||||||
|
#include "impeller/core/formats.h"
|
||||||
|
#include "impeller/core/texture_descriptor.h"
|
||||||
#include "impeller/display_list/dl_dispatcher.h"
|
#include "impeller/display_list/dl_dispatcher.h"
|
||||||
|
#include "impeller/renderer/backend/vulkan/command_buffer_vk.h"
|
||||||
|
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
||||||
#include "impeller/renderer/backend/vulkan/surface_context_vk.h"
|
#include "impeller/renderer/backend/vulkan/surface_context_vk.h"
|
||||||
|
#include "impeller/renderer/backend/vulkan/swapchain/surface_vk.h"
|
||||||
|
#include "impeller/renderer/render_target.h"
|
||||||
#include "impeller/renderer/surface.h"
|
#include "impeller/renderer/surface.h"
|
||||||
#include "impeller/typographer/backends/skia/typographer_context_skia.h"
|
#include "impeller/typographer/backends/skia/typographer_context_skia.h"
|
||||||
|
|
||||||
namespace flutter {
|
namespace flutter {
|
||||||
|
|
||||||
|
class WrappedTextureSourceVK : public impeller::TextureSourceVK {
|
||||||
|
public:
|
||||||
|
explicit WrappedTextureSourceVK(impeller::vk::Image image,
|
||||||
|
impeller::vk::ImageView image_view,
|
||||||
|
impeller::TextureDescriptor desc)
|
||||||
|
: TextureSourceVK(desc), image_(image), image_view_(image_view) {}
|
||||||
|
|
||||||
|
~WrappedTextureSourceVK() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
impeller::vk::Image GetImage() const override { return image_; }
|
||||||
|
|
||||||
|
impeller::vk::ImageView GetImageView() const override { return image_view_; }
|
||||||
|
|
||||||
|
impeller::vk::ImageView GetRenderTargetView() const override {
|
||||||
|
return image_view_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSwapchainImage() const override { return true; }
|
||||||
|
|
||||||
|
impeller::vk::Image image_;
|
||||||
|
impeller::vk::ImageView image_view_;
|
||||||
|
};
|
||||||
|
|
||||||
GPUSurfaceVulkanImpeller::GPUSurfaceVulkanImpeller(
|
GPUSurfaceVulkanImpeller::GPUSurfaceVulkanImpeller(
|
||||||
std::shared_ptr<impeller::Context> context) {
|
GPUSurfaceVulkanDelegate* delegate,
|
||||||
|
std::shared_ptr<impeller::Context> context)
|
||||||
|
: delegate_(delegate) {
|
||||||
if (!context || !context->IsValid()) {
|
if (!context || !context->IsValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -27,7 +62,7 @@ GPUSurfaceVulkanImpeller::GPUSurfaceVulkanImpeller(
|
|||||||
|
|
||||||
impeller_context_ = std::move(context);
|
impeller_context_ = std::move(context);
|
||||||
aiks_context_ = std::move(aiks_context);
|
aiks_context_ = std::move(aiks_context);
|
||||||
is_valid_ = true;
|
is_valid_ = !!aiks_context_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// |Surface|
|
// |Surface|
|
||||||
@ -51,17 +86,18 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceVulkanImpeller::AcquireFrame(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (delegate_ == nullptr) {
|
||||||
auto& context_vk = impeller::SurfaceContextVK::Cast(*impeller_context_);
|
auto& context_vk = impeller::SurfaceContextVK::Cast(*impeller_context_);
|
||||||
std::unique_ptr<impeller::Surface> surface = context_vk.AcquireNextSurface();
|
std::unique_ptr<impeller::Surface> surface =
|
||||||
|
context_vk.AcquireNextSurface();
|
||||||
|
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
FML_LOG(ERROR) << "No surface available.";
|
FML_LOG(ERROR) << "No surface available.";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cull_rect = surface->GetRenderTarget().GetRenderTargetSize();
|
|
||||||
|
|
||||||
impeller::RenderTarget render_target = surface->GetRenderTarget();
|
impeller::RenderTarget render_target = surface->GetRenderTarget();
|
||||||
|
auto cull_rect = render_target.GetRenderTargetSize();
|
||||||
|
|
||||||
SurfaceFrame::EncodeCallback encode_callback = [aiks_context =
|
SurfaceFrame::EncodeCallback encode_callback = [aiks_context =
|
||||||
aiks_context_, //
|
aiks_context_, //
|
||||||
@ -98,6 +134,145 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceVulkanImpeller::AcquireFrame(
|
|||||||
nullptr, // context result
|
nullptr, // context result
|
||||||
true // display list fallback
|
true // display list fallback
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
FlutterVulkanImage flutter_image = delegate_->AcquireImage(size);
|
||||||
|
if (!flutter_image.image) {
|
||||||
|
FML_LOG(ERROR) << "Invalid VkImage given by the embedder.";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
impeller::vk::Format vk_format =
|
||||||
|
static_cast<impeller::vk::Format>(flutter_image.format);
|
||||||
|
std::optional<impeller::PixelFormat> format =
|
||||||
|
impeller::VkFormatToImpellerFormat(vk_format);
|
||||||
|
if (!format.has_value()) {
|
||||||
|
FML_LOG(ERROR) << "Unsupported pixel format: "
|
||||||
|
<< impeller::vk::to_string(vk_format);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
impeller::vk::Image vk_image =
|
||||||
|
impeller::vk::Image(reinterpret_cast<VkImage>(flutter_image.image));
|
||||||
|
|
||||||
|
impeller::TextureDescriptor desc;
|
||||||
|
desc.format = format.value();
|
||||||
|
desc.size = impeller::ISize{size.width(), size.height()};
|
||||||
|
desc.storage_mode = impeller::StorageMode::kDevicePrivate;
|
||||||
|
desc.mip_count = 1;
|
||||||
|
desc.compression_type = impeller::CompressionType::kLossless;
|
||||||
|
desc.usage = impeller::TextureUsage::kRenderTarget;
|
||||||
|
|
||||||
|
impeller::ContextVK& context_vk =
|
||||||
|
impeller::ContextVK::Cast(*impeller_context_);
|
||||||
|
|
||||||
|
impeller::vk::ImageViewCreateInfo view_info = {};
|
||||||
|
view_info.viewType = impeller::vk::ImageViewType::e2D;
|
||||||
|
view_info.format = ToVKImageFormat(desc.format);
|
||||||
|
view_info.subresourceRange.aspectMask =
|
||||||
|
impeller::vk::ImageAspectFlagBits::eColor;
|
||||||
|
view_info.subresourceRange.baseMipLevel = 0u;
|
||||||
|
view_info.subresourceRange.baseArrayLayer = 0u;
|
||||||
|
view_info.subresourceRange.levelCount = 1;
|
||||||
|
view_info.subresourceRange.layerCount = 1;
|
||||||
|
view_info.image = vk_image;
|
||||||
|
|
||||||
|
auto [result, image_view] =
|
||||||
|
context_vk.GetDevice().createImageView(view_info);
|
||||||
|
if (result != impeller::vk::Result::eSuccess) {
|
||||||
|
FML_LOG(ERROR) << "Failed to create image view for provided image: "
|
||||||
|
<< impeller::vk::to_string(result);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transients_ == nullptr) {
|
||||||
|
transients_ = std::make_shared<impeller::SwapchainTransientsVK>(
|
||||||
|
impeller_context_, desc,
|
||||||
|
/*enable_msaa=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto wrapped_onscreen =
|
||||||
|
std::make_shared<WrappedTextureSourceVK>(vk_image, image_view, desc);
|
||||||
|
auto surface = impeller::SurfaceVK::WrapSwapchainImage(
|
||||||
|
transients_, wrapped_onscreen, [&]() -> bool { return true; });
|
||||||
|
impeller::RenderTarget render_target = surface->GetRenderTarget();
|
||||||
|
auto cull_rect = render_target.GetRenderTargetSize();
|
||||||
|
|
||||||
|
SurfaceFrame::EncodeCallback encode_callback = [aiks_context =
|
||||||
|
aiks_context_, //
|
||||||
|
render_target,
|
||||||
|
cull_rect //
|
||||||
|
](SurfaceFrame& surface_frame, DlCanvas* canvas) mutable -> bool {
|
||||||
|
if (!aiks_context) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto display_list = surface_frame.BuildDisplayList();
|
||||||
|
if (!display_list) {
|
||||||
|
FML_LOG(ERROR) << "Could not build display list for surface frame.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.width, cull_rect.height);
|
||||||
|
return impeller::RenderToOnscreen(aiks_context->GetContentContext(), //
|
||||||
|
render_target, //
|
||||||
|
display_list, //
|
||||||
|
sk_cull_rect, //
|
||||||
|
/*reset_host_buffer=*/true //
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
SurfaceFrame::SubmitCallback submit_callback =
|
||||||
|
[image = flutter_image, delegate = delegate_,
|
||||||
|
impeller_context = impeller_context_,
|
||||||
|
wrapped_onscreen](const SurfaceFrame&) -> bool {
|
||||||
|
TRACE_EVENT0("flutter", "GPUSurfaceVulkan::PresentImage");
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto& context = impeller::ContextVK::Cast(*impeller_context);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
/// Transition the image to color-attachment-optimal.
|
||||||
|
///
|
||||||
|
auto cmd_buffer = context.CreateCommandBuffer();
|
||||||
|
|
||||||
|
auto vk_final_cmd_buffer =
|
||||||
|
impeller::CommandBufferVK::Cast(*cmd_buffer).GetCommandBuffer();
|
||||||
|
{
|
||||||
|
impeller::BarrierVK barrier;
|
||||||
|
barrier.new_layout =
|
||||||
|
impeller::vk::ImageLayout::eColorAttachmentOptimal;
|
||||||
|
barrier.cmd_buffer = vk_final_cmd_buffer;
|
||||||
|
barrier.src_access =
|
||||||
|
impeller::vk::AccessFlagBits::eColorAttachmentWrite;
|
||||||
|
barrier.src_stage =
|
||||||
|
impeller::vk::PipelineStageFlagBits::eColorAttachmentOutput;
|
||||||
|
barrier.dst_access = {};
|
||||||
|
barrier.dst_stage =
|
||||||
|
impeller::vk::PipelineStageFlagBits::eBottomOfPipe;
|
||||||
|
|
||||||
|
if (!wrapped_onscreen->SetLayout(barrier).ok()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!context.GetCommandQueue()->Submit({cmd_buffer}).ok()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return delegate->PresentImage(reinterpret_cast<VkImage>(image.image),
|
||||||
|
static_cast<VkFormat>(image.format));
|
||||||
|
};
|
||||||
|
|
||||||
|
SurfaceFrame::FramebufferInfo framebuffer_info{.supports_readback = true};
|
||||||
|
|
||||||
|
return std::make_unique<SurfaceFrame>(nullptr, // surface
|
||||||
|
framebuffer_info, // framebuffer info
|
||||||
|
encode_callback, // encode callback
|
||||||
|
submit_callback,
|
||||||
|
size, // frame size
|
||||||
|
nullptr, // context result
|
||||||
|
true // display list fallback
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// |Surface|
|
// |Surface|
|
||||||
|
@ -12,12 +12,14 @@
|
|||||||
#include "flutter/impeller/display_list/aiks_context.h"
|
#include "flutter/impeller/display_list/aiks_context.h"
|
||||||
#include "flutter/impeller/renderer/context.h"
|
#include "flutter/impeller/renderer/context.h"
|
||||||
#include "flutter/shell/gpu/gpu_surface_vulkan_delegate.h"
|
#include "flutter/shell/gpu/gpu_surface_vulkan_delegate.h"
|
||||||
|
#include "impeller/renderer/backend/vulkan/swapchain/swapchain_transients_vk.h"
|
||||||
|
|
||||||
namespace flutter {
|
namespace flutter {
|
||||||
|
|
||||||
class GPUSurfaceVulkanImpeller final : public Surface {
|
class GPUSurfaceVulkanImpeller final : public Surface {
|
||||||
public:
|
public:
|
||||||
explicit GPUSurfaceVulkanImpeller(std::shared_ptr<impeller::Context> context);
|
explicit GPUSurfaceVulkanImpeller(GPUSurfaceVulkanDelegate* delegate,
|
||||||
|
std::shared_ptr<impeller::Context> context);
|
||||||
|
|
||||||
// |Surface|
|
// |Surface|
|
||||||
~GPUSurfaceVulkanImpeller() override;
|
~GPUSurfaceVulkanImpeller() override;
|
||||||
@ -26,8 +28,10 @@ class GPUSurfaceVulkanImpeller final : public Surface {
|
|||||||
bool IsValid() override;
|
bool IsValid() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
GPUSurfaceVulkanDelegate* delegate_;
|
||||||
std::shared_ptr<impeller::Context> impeller_context_;
|
std::shared_ptr<impeller::Context> impeller_context_;
|
||||||
std::shared_ptr<impeller::AiksContext> aiks_context_;
|
std::shared_ptr<impeller::AiksContext> aiks_context_;
|
||||||
|
std::shared_ptr<impeller::SwapchainTransientsVK> transients_;
|
||||||
bool is_valid_ = false;
|
bool is_valid_ = false;
|
||||||
|
|
||||||
// |Surface|
|
// |Surface|
|
||||||
|
@ -25,7 +25,7 @@ AndroidSurfaceVKImpeller::AndroidSurfaceVKImpeller(
|
|||||||
impeller::ContextVK::Cast(*android_context->GetImpellerContext());
|
impeller::ContextVK::Cast(*android_context->GetImpellerContext());
|
||||||
surface_context_vk_ = context_vk.CreateSurfaceContext();
|
surface_context_vk_ = context_vk.CreateSurfaceContext();
|
||||||
eager_gpu_surface_ =
|
eager_gpu_surface_ =
|
||||||
std::make_unique<GPUSurfaceVulkanImpeller>(surface_context_vk_);
|
std::make_unique<GPUSurfaceVulkanImpeller>(nullptr, surface_context_vk_);
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidSurfaceVKImpeller::~AndroidSurfaceVKImpeller() = default;
|
AndroidSurfaceVKImpeller::~AndroidSurfaceVKImpeller() = default;
|
||||||
@ -57,7 +57,7 @@ std::unique_ptr<Surface> AndroidSurfaceVKImpeller::CreateGPUSurface(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GPUSurfaceVulkanImpeller> gpu_surface =
|
std::unique_ptr<GPUSurfaceVulkanImpeller> gpu_surface =
|
||||||
std::make_unique<GPUSurfaceVulkanImpeller>(surface_context_vk_);
|
std::make_unique<GPUSurfaceVulkanImpeller>(nullptr, surface_context_vk_);
|
||||||
|
|
||||||
if (!gpu_surface->IsValid()) {
|
if (!gpu_surface->IsValid()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -171,6 +171,13 @@ template("embedder_source_set") {
|
|||||||
"embedder_surface_vulkan.h",
|
"embedder_surface_vulkan.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if (impeller_supports_rendering) {
|
||||||
|
sources += [
|
||||||
|
"embedder_surface_vulkan_impeller.cc",
|
||||||
|
"embedder_surface_vulkan_impeller.h",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
deps += [
|
deps += [
|
||||||
"//flutter/flutter_vma:flutter_skia_vma",
|
"//flutter/flutter_vma:flutter_skia_vma",
|
||||||
"//flutter/vulkan/procs",
|
"//flutter/vulkan/procs",
|
||||||
|
@ -615,7 +615,8 @@ InferVulkanPlatformViewCreationCallback(
|
|||||||
const flutter::PlatformViewEmbedder::PlatformDispatchTable&
|
const flutter::PlatformViewEmbedder::PlatformDispatchTable&
|
||||||
platform_dispatch_table,
|
platform_dispatch_table,
|
||||||
std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
|
std::unique_ptr<flutter::EmbedderExternalViewEmbedder>
|
||||||
external_view_embedder) {
|
external_view_embedder,
|
||||||
|
bool enable_impeller) {
|
||||||
if (config->type != kVulkan) {
|
if (config->type != kVulkan) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -655,15 +656,88 @@ InferVulkanPlatformViewCreationCallback(
|
|||||||
auto proc_addr =
|
auto proc_addr =
|
||||||
vulkan_get_instance_proc_address(vk_instance, "vkGetInstanceProcAddr");
|
vulkan_get_instance_proc_address(vk_instance, "vkGetInstanceProcAddr");
|
||||||
|
|
||||||
flutter::EmbedderSurfaceVulkan::VulkanDispatchTable vulkan_dispatch_table = {
|
std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
|
||||||
|
std::move(external_view_embedder);
|
||||||
|
|
||||||
|
#if IMPELLER_SUPPORTS_RENDERING
|
||||||
|
if (enable_impeller) {
|
||||||
|
flutter::EmbedderSurfaceVulkanImpeller::VulkanDispatchTable
|
||||||
|
vulkan_dispatch_table = {
|
||||||
.get_instance_proc_address =
|
.get_instance_proc_address =
|
||||||
reinterpret_cast<PFN_vkGetInstanceProcAddr>(proc_addr),
|
reinterpret_cast<PFN_vkGetInstanceProcAddr>(proc_addr),
|
||||||
.get_next_image = vulkan_get_next_image,
|
.get_next_image = vulkan_get_next_image,
|
||||||
.present_image = vulkan_present_image_callback,
|
.present_image = vulkan_present_image_callback,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<flutter::EmbedderExternalViewEmbedder> view_embedder =
|
std::unique_ptr<flutter::EmbedderSurfaceVulkanImpeller> embedder_surface =
|
||||||
std::move(external_view_embedder);
|
std::make_unique<flutter::EmbedderSurfaceVulkanImpeller>(
|
||||||
|
config->vulkan.version, vk_instance,
|
||||||
|
config->vulkan.enabled_instance_extension_count,
|
||||||
|
config->vulkan.enabled_instance_extensions,
|
||||||
|
config->vulkan.enabled_device_extension_count,
|
||||||
|
config->vulkan.enabled_device_extensions,
|
||||||
|
static_cast<VkPhysicalDevice>(config->vulkan.physical_device),
|
||||||
|
static_cast<VkDevice>(config->vulkan.device),
|
||||||
|
config->vulkan.queue_family_index,
|
||||||
|
static_cast<VkQueue>(config->vulkan.queue), vulkan_dispatch_table,
|
||||||
|
view_embedder);
|
||||||
|
|
||||||
|
return fml::MakeCopyable(
|
||||||
|
[embedder_surface = std::move(embedder_surface),
|
||||||
|
platform_dispatch_table,
|
||||||
|
external_view_embedder =
|
||||||
|
std::move(view_embedder)](flutter::Shell& shell) mutable {
|
||||||
|
return std::make_unique<flutter::PlatformViewEmbedder>(
|
||||||
|
shell, // delegate
|
||||||
|
shell.GetTaskRunners(), // task runners
|
||||||
|
std::move(embedder_surface), // embedder surface
|
||||||
|
platform_dispatch_table, // platform dispatch table
|
||||||
|
std::move(external_view_embedder) // external view embedder
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
flutter::EmbedderSurfaceVulkan::VulkanDispatchTable vulkan_dispatch_table =
|
||||||
|
{
|
||||||
|
.get_instance_proc_address =
|
||||||
|
reinterpret_cast<PFN_vkGetInstanceProcAddr>(proc_addr),
|
||||||
|
.get_next_image = vulkan_get_next_image,
|
||||||
|
.present_image = vulkan_present_image_callback,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<flutter::EmbedderSurfaceVulkan> embedder_surface =
|
||||||
|
std::make_unique<flutter::EmbedderSurfaceVulkan>(
|
||||||
|
config->vulkan.version, vk_instance,
|
||||||
|
config->vulkan.enabled_instance_extension_count,
|
||||||
|
config->vulkan.enabled_instance_extensions,
|
||||||
|
config->vulkan.enabled_device_extension_count,
|
||||||
|
config->vulkan.enabled_device_extensions,
|
||||||
|
static_cast<VkPhysicalDevice>(config->vulkan.physical_device),
|
||||||
|
static_cast<VkDevice>(config->vulkan.device),
|
||||||
|
config->vulkan.queue_family_index,
|
||||||
|
static_cast<VkQueue>(config->vulkan.queue), vulkan_dispatch_table,
|
||||||
|
view_embedder);
|
||||||
|
|
||||||
|
return fml::MakeCopyable(
|
||||||
|
[embedder_surface = std::move(embedder_surface),
|
||||||
|
platform_dispatch_table,
|
||||||
|
external_view_embedder =
|
||||||
|
std::move(view_embedder)](flutter::Shell& shell) mutable {
|
||||||
|
return std::make_unique<flutter::PlatformViewEmbedder>(
|
||||||
|
shell, // delegate
|
||||||
|
shell.GetTaskRunners(), // task runners
|
||||||
|
std::move(embedder_surface), // embedder surface
|
||||||
|
platform_dispatch_table, // platform dispatch table
|
||||||
|
std::move(external_view_embedder) // external view embedder
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
flutter::EmbedderSurfaceVulkan::VulkanDispatchTable vulkan_dispatch_table = {
|
||||||
|
.get_instance_proc_address =
|
||||||
|
reinterpret_cast<PFN_vkGetInstanceProcAddr>(proc_addr),
|
||||||
|
.get_next_image = vulkan_get_next_image,
|
||||||
|
.present_image = vulkan_present_image_callback,
|
||||||
|
};
|
||||||
|
|
||||||
std::unique_ptr<flutter::EmbedderSurfaceVulkan> embedder_surface =
|
std::unique_ptr<flutter::EmbedderSurfaceVulkan> embedder_surface =
|
||||||
std::make_unique<flutter::EmbedderSurfaceVulkan>(
|
std::make_unique<flutter::EmbedderSurfaceVulkan>(
|
||||||
@ -690,6 +764,7 @@ InferVulkanPlatformViewCreationCallback(
|
|||||||
std::move(external_view_embedder) // external view embedder
|
std::move(external_view_embedder) // external view embedder
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
#endif // // IMPELLER_SUPPORTS_RENDERING
|
||||||
#else // SHELL_ENABLE_VULKAN
|
#else // SHELL_ENABLE_VULKAN
|
||||||
FML_LOG(ERROR) << "This Flutter Engine does not support Vulkan rendering.";
|
FML_LOG(ERROR) << "This Flutter Engine does not support Vulkan rendering.";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -762,7 +837,7 @@ InferPlatformViewCreationCallback(
|
|||||||
case kVulkan:
|
case kVulkan:
|
||||||
return InferVulkanPlatformViewCreationCallback(
|
return InferVulkanPlatformViewCreationCallback(
|
||||||
config, user_data, platform_dispatch_table,
|
config, user_data, platform_dispatch_table,
|
||||||
std::move(external_view_embedder));
|
std::move(external_view_embedder), enable_impeller);
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -1434,12 +1509,17 @@ CreateEmbedderRenderTarget(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kFlutterBackingStoreTypeVulkan: {
|
case kFlutterBackingStoreTypeVulkan: {
|
||||||
auto skia_surface =
|
if (enable_impeller) {
|
||||||
MakeSkSurfaceFromBackingStore(context, config, &backing_store.vulkan);
|
FML_LOG(ERROR) << "Unimplemented";
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
auto skia_surface = MakeSkSurfaceFromBackingStore(
|
||||||
|
context, config, &backing_store.vulkan);
|
||||||
render_target = MakeRenderTargetFromSkSurface(
|
render_target = MakeRenderTargetFromSkSurface(
|
||||||
backing_store, std::move(skia_surface), collect_callback.Release());
|
backing_store, std::move(skia_surface), collect_callback.Release());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!render_target) {
|
if (!render_target) {
|
||||||
|
@ -0,0 +1,124 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include "flutter/shell/platform/embedder/embedder_surface_vulkan_impeller.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "flutter/impeller/entity/vk/entity_shaders_vk.h"
|
||||||
|
#include "flutter/impeller/entity/vk/framebuffer_blend_shaders_vk.h"
|
||||||
|
#include "flutter/impeller/entity/vk/modern_shaders_vk.h"
|
||||||
|
#include "flutter/shell/gpu/gpu_surface_vulkan.h"
|
||||||
|
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
||||||
|
#include "include/gpu/ganesh/GrDirectContext.h"
|
||||||
|
#include "shell/gpu/gpu_surface_vulkan_impeller.h"
|
||||||
|
|
||||||
|
namespace flutter {
|
||||||
|
|
||||||
|
EmbedderSurfaceVulkanImpeller::EmbedderSurfaceVulkanImpeller(
|
||||||
|
uint32_t version,
|
||||||
|
VkInstance instance,
|
||||||
|
size_t instance_extension_count,
|
||||||
|
const char** instance_extensions,
|
||||||
|
size_t device_extension_count,
|
||||||
|
const char** device_extensions,
|
||||||
|
VkPhysicalDevice physical_device,
|
||||||
|
VkDevice device,
|
||||||
|
uint32_t queue_family_index,
|
||||||
|
VkQueue queue,
|
||||||
|
const VulkanDispatchTable& vulkan_dispatch_table,
|
||||||
|
std::shared_ptr<EmbedderExternalViewEmbedder> external_view_embedder)
|
||||||
|
: vk_(fml::MakeRefCounted<vulkan::VulkanProcTable>(
|
||||||
|
vulkan_dispatch_table.get_instance_proc_address)),
|
||||||
|
vulkan_dispatch_table_(vulkan_dispatch_table),
|
||||||
|
external_view_embedder_(std::move(external_view_embedder)) {
|
||||||
|
// Make sure all required members of the dispatch table are checked.
|
||||||
|
if (!vulkan_dispatch_table_.get_instance_proc_address ||
|
||||||
|
!vulkan_dispatch_table_.get_next_image ||
|
||||||
|
!vulkan_dispatch_table_.present_image) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<fml::Mapping>> shader_mappings = {
|
||||||
|
std::make_shared<fml::NonOwnedMapping>(impeller_entity_shaders_vk_data,
|
||||||
|
impeller_entity_shaders_vk_length),
|
||||||
|
std::make_shared<fml::NonOwnedMapping>(impeller_modern_shaders_vk_data,
|
||||||
|
impeller_modern_shaders_vk_length),
|
||||||
|
std::make_shared<fml::NonOwnedMapping>(
|
||||||
|
impeller_framebuffer_blend_shaders_vk_data,
|
||||||
|
impeller_framebuffer_blend_shaders_vk_length),
|
||||||
|
};
|
||||||
|
impeller::ContextVK::Settings settings;
|
||||||
|
settings.shader_libraries_data = shader_mappings;
|
||||||
|
settings.proc_address_callback =
|
||||||
|
vulkan_dispatch_table.get_instance_proc_address;
|
||||||
|
|
||||||
|
impeller::ContextVK::EmbedderData data;
|
||||||
|
data.instance = instance;
|
||||||
|
data.physical_device = physical_device;
|
||||||
|
data.device = device;
|
||||||
|
data.queue = queue;
|
||||||
|
data.queue_family_index = queue_family_index;
|
||||||
|
data.instance_extensions.reserve(instance_extension_count);
|
||||||
|
for (auto i = 0u; i < instance_extension_count; i++) {
|
||||||
|
data.instance_extensions.push_back(std::string{instance_extensions[i]});
|
||||||
|
}
|
||||||
|
data.device_extensions.reserve(device_extension_count);
|
||||||
|
for (auto i = 0u; i < device_extension_count; i++) {
|
||||||
|
data.device_extensions.push_back(std::string{device_extensions[i]});
|
||||||
|
}
|
||||||
|
settings.embedder_data = data;
|
||||||
|
|
||||||
|
context_ = impeller::ContextVK::Create(std::move(settings));
|
||||||
|
if (!context_) {
|
||||||
|
FML_LOG(ERROR) << "Failed to initialize Vulkan Context.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FML_LOG(IMPORTANT) << "Using the Impeller rendering backend (Vulkan).";
|
||||||
|
|
||||||
|
valid_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmbedderSurfaceVulkanImpeller::~EmbedderSurfaceVulkanImpeller() {}
|
||||||
|
|
||||||
|
std::shared_ptr<impeller::Context>
|
||||||
|
EmbedderSurfaceVulkanImpeller::CreateImpellerContext() const {
|
||||||
|
return context_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// |GPUSurfaceVulkanDelegate|
|
||||||
|
const vulkan::VulkanProcTable& EmbedderSurfaceVulkanImpeller::vk() {
|
||||||
|
return *vk_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// |GPUSurfaceVulkanDelegate|
|
||||||
|
FlutterVulkanImage EmbedderSurfaceVulkanImpeller::AcquireImage(
|
||||||
|
const SkISize& size) {
|
||||||
|
return vulkan_dispatch_table_.get_next_image(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// |GPUSurfaceVulkanDelegate|
|
||||||
|
bool EmbedderSurfaceVulkanImpeller::PresentImage(VkImage image,
|
||||||
|
VkFormat format) {
|
||||||
|
return vulkan_dispatch_table_.present_image(image, format);
|
||||||
|
}
|
||||||
|
|
||||||
|
// |EmbedderSurface|
|
||||||
|
bool EmbedderSurfaceVulkanImpeller::IsValid() const {
|
||||||
|
return valid_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// |EmbedderSurface|
|
||||||
|
std::unique_ptr<Surface> EmbedderSurfaceVulkanImpeller::CreateGPUSurface() {
|
||||||
|
return std::make_unique<GPUSurfaceVulkanImpeller>(this, context_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// |EmbedderSurface|
|
||||||
|
sk_sp<GrDirectContext> EmbedderSurfaceVulkanImpeller::CreateResourceContext()
|
||||||
|
const {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace flutter
|
@ -0,0 +1,81 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_SURFACE_VULKAN_IMPELLER_H_
|
||||||
|
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_SURFACE_VULKAN_IMPELLER_H_
|
||||||
|
|
||||||
|
#include "flutter/shell/common/context_options.h"
|
||||||
|
#include "flutter/shell/gpu/gpu_surface_vulkan.h"
|
||||||
|
#include "flutter/shell/gpu/gpu_surface_vulkan_delegate.h"
|
||||||
|
#include "flutter/shell/platform/embedder/embedder.h"
|
||||||
|
#include "flutter/shell/platform/embedder/embedder_external_view_embedder.h"
|
||||||
|
#include "flutter/shell/platform/embedder/embedder_surface.h"
|
||||||
|
#include "flutter/vulkan/procs/vulkan_proc_table.h"
|
||||||
|
#include "impeller/renderer/backend/vulkan/context_vk.h"
|
||||||
|
|
||||||
|
namespace flutter {
|
||||||
|
|
||||||
|
class EmbedderSurfaceVulkanImpeller final : public EmbedderSurface,
|
||||||
|
public GPUSurfaceVulkanDelegate {
|
||||||
|
public:
|
||||||
|
struct VulkanDispatchTable {
|
||||||
|
PFN_vkGetInstanceProcAddr get_instance_proc_address; // required
|
||||||
|
std::function<FlutterVulkanImage(const SkISize& frame_size)>
|
||||||
|
get_next_image; // required
|
||||||
|
std::function<bool(VkImage image, VkFormat format)>
|
||||||
|
present_image; // required
|
||||||
|
};
|
||||||
|
|
||||||
|
EmbedderSurfaceVulkanImpeller(
|
||||||
|
uint32_t version,
|
||||||
|
VkInstance instance,
|
||||||
|
size_t instance_extension_count,
|
||||||
|
const char** instance_extensions,
|
||||||
|
size_t device_extension_count,
|
||||||
|
const char** device_extensions,
|
||||||
|
VkPhysicalDevice physical_device,
|
||||||
|
VkDevice device,
|
||||||
|
uint32_t queue_family_index,
|
||||||
|
VkQueue queue,
|
||||||
|
const VulkanDispatchTable& vulkan_dispatch_table,
|
||||||
|
std::shared_ptr<EmbedderExternalViewEmbedder> external_view_embedder);
|
||||||
|
|
||||||
|
~EmbedderSurfaceVulkanImpeller() override;
|
||||||
|
|
||||||
|
// |GPUSurfaceVulkanDelegate|
|
||||||
|
const vulkan::VulkanProcTable& vk() override;
|
||||||
|
|
||||||
|
// |GPUSurfaceVulkanDelegate|
|
||||||
|
FlutterVulkanImage AcquireImage(const SkISize& size) override;
|
||||||
|
|
||||||
|
// |GPUSurfaceVulkanDelegate|
|
||||||
|
bool PresentImage(VkImage image, VkFormat format) override;
|
||||||
|
|
||||||
|
// |GPUSurfaceVulkanDelegate|
|
||||||
|
std::shared_ptr<impeller::Context> CreateImpellerContext() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool valid_ = false;
|
||||||
|
fml::RefPtr<vulkan::VulkanProcTable> vk_;
|
||||||
|
VulkanDispatchTable vulkan_dispatch_table_;
|
||||||
|
std::shared_ptr<EmbedderExternalViewEmbedder> external_view_embedder_;
|
||||||
|
std::shared_ptr<impeller::ContextVK> context_;
|
||||||
|
|
||||||
|
// |EmbedderSurface|
|
||||||
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
// |EmbedderSurface|
|
||||||
|
std::unique_ptr<Surface> CreateGPUSurface() override;
|
||||||
|
|
||||||
|
// |EmbedderSurface|
|
||||||
|
sk_sp<GrDirectContext> CreateResourceContext() const override;
|
||||||
|
|
||||||
|
EmbedderSurfaceVulkanImpeller(const EmbedderSurfaceVulkanImpeller&) = delete;
|
||||||
|
EmbedderSurfaceVulkanImpeller& operator=(
|
||||||
|
const EmbedderSurfaceVulkanImpeller&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace flutter
|
||||||
|
|
||||||
|
#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_SURFACE_VULKAN_IMPELLER_H_
|
@ -26,6 +26,9 @@
|
|||||||
|
|
||||||
#ifdef SHELL_ENABLE_VULKAN
|
#ifdef SHELL_ENABLE_VULKAN
|
||||||
#include "flutter/shell/platform/embedder/embedder_surface_vulkan.h"
|
#include "flutter/shell/platform/embedder/embedder_surface_vulkan.h"
|
||||||
|
#ifdef IMPELLER_SUPPORTS_RENDERING
|
||||||
|
#include "flutter/shell/platform/embedder/embedder_surface_vulkan_impeller.h"
|
||||||
|
#endif // IMPELLER_SUPPORTS_RENDERING
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace flutter {
|
namespace flutter {
|
||||||
|
@ -211,7 +211,7 @@ class TesterPlatformView : public PlatformView,
|
|||||||
if (delegate_.OnPlatformViewGetSettings().enable_impeller) {
|
if (delegate_.OnPlatformViewGetSettings().enable_impeller) {
|
||||||
FML_DCHECK(impeller_context_holder_.context);
|
FML_DCHECK(impeller_context_holder_.context);
|
||||||
auto surface = std::make_unique<GPUSurfaceVulkanImpeller>(
|
auto surface = std::make_unique<GPUSurfaceVulkanImpeller>(
|
||||||
impeller_context_holder_.surface_context);
|
nullptr, impeller_context_holder_.surface_context);
|
||||||
FML_DCHECK(surface->IsValid());
|
FML_DCHECK(surface->IsValid());
|
||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user